写于:2020-01-09

# 一、线程安全与数据同步

当多个线程间存在共享的资源时,便会存在线程安全的问题。为了解决共享资源的安全问题,就需要解决共享资源在各个线程间的数据同步问题。

# 二、数据不一致

当多个线程对一个共享的数据进行操作的时候,就会出现数据不一致的问题。

# 1、简单案例引出线程安全问题。

案例:多个线程多一个数字进行累加,当累加到指定数量时,结束

public class SimpleThread {

    public static void main(String[] args) throws InterruptedException {
        final TaskRunnable taskRunnable = new TaskRunnable();
        List<Thread> threads = IntStream.rangeClosed(1, 4).mapToObj(loopTimes -> {
            return new Thread(taskRunnable, "T" + loopTimes);
        }).collect(Collectors.toList());
        threads.stream().forEach(Thread::start);
    }

    public static class TaskRunnable implements Runnable{
        /** 共享的数据 **/
        private int index = 0;
        /** 结束累加的阈值 **/
        private static final int max = 15000;
        @Override
        public void run() {
            while(index <= max){
                System.out.println(Thread.currentThread() +":" + (index++));
            }
        }
    }
}

多次运行可能出现问题如下

1、某个值重复出现

2、某个值被忽略没有出现

3、总数超过了最大值

# 2、问题分析

index++;不是一个原子操作;他分为三个部分

a、取值

b、累加

c、赋值

真个累加操作可以分为如下几个步骤:

  • 1、while 判断
  • 2、index 取值
  • 3、index 累加
  • 4、累加值 赋值给 index
  • 5、打印 index 值

# 某个值重复出现

两个线程,线程1和线程2。

线程 2 拿到 CPU 执行权进行操作: 1[while判断],2[index取值],3[index累加] 。然后释放了cpu执行权。

线程 1 拿到 CPU 执行权进行操作: 1[while判断],2[index取值],3[index累加],4[赋值],5[打印],此时打印结果 index =2。然后释放 cpu 执行权。

线程 2 拿到 CPU 执行权进行操作: 4[赋值],5[打印],此时打印结果 index =2,。

出现重复值打印问题。

# 某个值被忽略

两个线程,线程1和线程2。

线程 2 拿到 CPU 执行权进行操作:1[while判断],2[index取值],3[index累加],4[赋值]。然后释放 cpu 执行权

线程 1 拿到 CPU 执行权进行操作:1[while判断],2[index取值],3[index累加],4[赋值],5[打印],此时打印结果 index =3,然后释放 CPU 执行权。

线程 2 拿到 CPU 执行权进行操作:5[打印],此时打印结果为 3。

出现忽略问题,2的打印被忽略了。

# 超过最大值

两个线程,线程1和线程2。

最大值为 500.此时 index = 499。

线程 1 拿到 CPU 执行权进行操作:1[while判断],然后释放 CPU 执行权。

线程 2 拿到 CPU 执行权进行操作:1[while判断],然后释放 CPU 执行权。

线程 1 拿到 CPU 执行权进行操作:2[index取值],3[index累加],4[赋值],5[打印]。此时 index 为最大值 500.

线程 2 由于已经通过 1[while] 的判断,所以能够接着操作:2[index取值],3[index累加],4[赋值],5[打印],此时 index 超出最大值,结果为 501.

出现超过最大值问题。

# 三、问题总结

出现线程安全和数据不一致的问题,都是因为多个线程同时对一个共享资源同时进行操作造成的。

精彩内容推送,请关注公众号!
最近更新时间: 4/16/2020, 8:37:50 PM