多线程(二)线程安全篇

2019-11-19  本文已影响0人  丶行一

上一篇讲到多线程如何使用,多线程使用时特别应该注意的是线程安全问题,本篇将专门讲述问题原因和解决方案

为什么:

为什么出现多线程安全问题


jmm模型.jpg

什么时候出现多线程安全问题


怎么办:如何解决多线程安全的问题

多线程安全的三个特性

@Slf4j
public class ThreadNotSafeDemo {
    public static void main(String[] args) throws Exception{
        JobAdd jobAdd=new JobAdd();
        for(int i=0;i<10;i++){
            new Thread(jobAdd,"thread "+i).start();
        }
        Thread.sleep(1000);
        log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),jobAdd.getTotal());
    }
}
@Slf4j
@Data
class JobAdd implements Runnable{
    private int total=0;
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            try {
                // 必须加简单的sleep,否则可能当前线程在下一个线程启动前就跑完了,演示不出效果
                Thread.sleep(10l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            total++;
        }
        log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),total);
    }
}

打印结果如下:
05:56:18.109 [thread 1] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 1 ,total is 912
05:56:18.119 [thread 4] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 4 ,total is 919
05:56:18.119 [thread 9] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 9 ,total is 915
05:56:18.119 [thread 8] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 8 ,total is 917
05:56:18.119 [thread 0] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 0 ,total is 919
05:56:18.132 [thread 5] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 5 ,total is 923
05:56:18.132 [thread 3] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 3 ,total is 924
05:56:18.132 [thread 6] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 6 ,total is 924
05:56:18.132 [thread 2] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 2 ,total is 925
05:56:18.132 [thread 7] DEBUG com.dz.demo.multiThread.JobAdd - thread is thread 7 ,total is 923
05:56:18.993 [main] DEBUG com.dz.demo.multiThread.ThreadNotSafeDemo - thread is main ,total is 925

要实现线程安全的几个方案

@Slf4j
public class SynchronizedUseDemo {
    public static void main(String[] args) throws Exception{
        SafeJobAdd jobAdd=new SafeJobAdd();
        for(int i=0;i<10;i++){
            new Thread(jobAdd,"thread "+i).start();
        }
        Thread.sleep(3000l);
        log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),jobAdd.getTotal());
    }
}

@Slf4j
@Data
class SafeJobAdd implements Runnable{
    private int total=0;
    @Override
    public void run() {
        // 使用了同步关键字synchronized
        synchronized (this){
            for (int i=0;i<100;i++){
                try {
                    Thread.sleep(2l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                total++;
            }
            log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),total);
        }

    }
}
打印结果是:
06:36:35.800 [thread 0] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 0 ,total is 100
06:36:36.042 [thread 9] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 9 ,total is 200
06:36:36.290 [thread 8] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 8 ,total is 300
06:36:36.539 [thread 7] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 7 ,total is 400
06:36:36.787 [thread 6] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 6 ,total is 500
06:36:37.040 [thread 5] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 5 ,total is 600
06:36:37.292 [thread 4] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 4 ,total is 700
06:36:37.541 [thread 3] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 3 ,total is 800
06:36:37.793 [thread 2] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 2 ,total is 900
06:36:38.043 [thread 1] DEBUG com.dz.demo.multiThread.SafeJobAdd - thread is thread 1 ,total is 1000
06:36:38.554 [main] DEBUG com.dz.demo.multiThread.SynchronizedUseDemo - thread is main ,total is 1000

@Slf4j
public class LockUseDemo {
    public static void main(String[] args) throws Exception{
        LockJobAdd jobAdd=new LockJobAdd();
        for(int i=0;i<10;i++){
            new Thread(jobAdd,"thread "+i).start();
        }
        Thread.sleep(3000l);
        log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),jobAdd.getTotal());
    }
}

@Slf4j
@Data
class LockJobAdd implements Runnable{
    private int total=0;
    private ReentrantLock lock=new ReentrantLock();
    @Override
    public void run() {
            for (int i=0;i<100;i++){
                try {
                    Thread.sleep(2l);
                    lock.lock();
                    total++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                    lock.unlock();
                }
            }
            log.debug("thread is {} ,total is {}",Thread.currentThread().getName(),total);
    }
}
打印如下:
06:54:22.861 [thread 7] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 7 ,total is 994
06:54:22.862 [thread 4] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 4 ,total is 997
06:54:22.861 [thread 9] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 9 ,total is 994
06:54:22.861 [thread 8] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 8 ,total is 994
06:54:22.862 [thread 3] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 3 ,total is 999
06:54:22.861 [thread 5] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 5 ,total is 994
06:54:22.862 [thread 0] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 0 ,total is 997
06:54:22.861 [thread 1] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 1 ,total is 998
06:54:22.861 [thread 2] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 2 ,total is 994
06:54:22.862 [thread 6] DEBUG com.dz.demo.multiThread.LockJobAdd - thread is thread 6 ,total is 1000
06:54:25.633 [main] DEBUG com.dz.demo.multiThread.LockUseDemo - thread is main ,total is 1000
上一篇 下一篇

猜你喜欢

热点阅读