美文网首页
两个线程同时执行循环操作

两个线程同时执行循环操作

作者: 雁阵惊寒_zhn | 来源:发表于2020-10-09 20:27 被阅读0次

题目

i初始值为0
两个线程同时执行循环操作,在不加任何同步下循环执行i++,i可能出现的最小值是多少?
或者
i++在两个线程分别执行100次,最大值和最小值分别多少?

如下示例代码,i的最大值和最小值分别多少

public class TwoThreadForLoop {
    private final int N = 100;
    private int i = 0;

    public class ForLoopTest extends Thread{
        @Override
        public void run() {
            for (int j = 0; j < N; j++){
                i++;
            }
            System.out.println(Thread.currentThread().getName());
        }
    }

    public void runTest(){
        ForLoopTest t1 = new ForLoopTest();
        ForLoopTest t2 = new ForLoopTest();
        t1.start();
        t2.start();
    }

    public int getI(){
        return i;
    }

    public static void main(String[] args){
        TwoThreadForLoop loop = new TwoThreadForLoop();
        loop.runTest();
        System.out.println("i = " + loop.getI());
    }
}

解析

Java内存模型有工作内存和主内存概念区别,每条线程都操作自己独有的工作内存,不同线程之间的数据通过主内存进行交换。具体可以参考Java内存模型(Java Memory Model, JMM)

在上面的代码中变量i的访问,两条线程都是基于自己工作内存进行操作,然后通过主内存进行数据的交换。i最终可能有多种不同的值。但是两条线程各自执行100次自增1的操作,最多也只会将i加到200,而绝对不会超过这个值。

所以第一个问题,最大值是200

而最小值是2。这时两条线程的执行轨迹如下所述(假设两条线程分别为线程A和线程B):

  1. 线程B暂时没执行,线程A执行i++操作99次后写回主内存,此时主内存i=99;
  2. 线程B在线程A写回内存前读到i=0,并且执行一次i++操作后,写回主内存,会覆盖掉线程A的执行结果,此时主内存i=1;
  3. 线程A读取i=1,执行最后一次i++操作,线程A工作内存中i=2,这次还没有写回主内存,主内存仍旧是i=1;
  4. 线程B在i=1基础上执行了余下的99次i++操作,等到结果i=100,写回主内存中,此时主内存i=100;
  5. 第3步中线程A此时将自己工作内存中的i=2写回主内存,覆盖之前的结果,主内存中最终i=2。

上面的结果是一种理论的分析,因为线程执行速度很快,两条线程真正执行时很难产生i=2的结果,概率极低。执行上面的代码会随机产生不同的结果,所以在实际开发中要注意多线程情况下数据的不一致,对于共享的数据要进行加锁。

下面是随机执行5次产生的结果,也是并发带来的数据不一致问题:
第一次:

Thread-1
Thread-0
i = 120

第二次:

i = 127
Thread-0
Thread-1

第三次:

i = 100
Thread-1
Thread-0

第四次:

Thread-0
Thread-1
i = 200

第五次:

i = 68
Thread-1
Thread-0

相关文章

  • 两个线程同时执行循环操作

    题目 i初始值为0两个线程同时执行循环操作,在不加任何同步下循环执行i++,i可能出现的最小值是多少?或者i++在...

  • 由浅入深讲解JUC下 CAS + Lock

    CAS 什么是原子(atomic)操作: 多线程中的原子操作类似于数据库中的同时执行AB两个语句,要么同时执行成功...

  • 原子操作CAS

    原子操作 假设有A、B两个操作,从执行A操作的线程来看,执行B操作的线程要么完全执行B操作,要么完全不执行B操...

  • 无锁、自旋锁、偏向锁、轻量级锁和重量级锁

    无锁 无锁是指线程通过无限循环来执行更新操作,如果执行成功就退出循环,如果执行失败(有其他线程更新了值),则继续执...

  • 事件循环

    0. 为什么有事件循环 我们知道 JS 是单线程非阻塞执行的。单线程很好理解,可以避免多线程同时对某些资源操作时的...

  • 多线程综合案例

    数字加减 设计四个线程对象,两个线程执行减操作,两个线程执行加操作; 生产电脑 设计一个生产电脑和搬运电脑类,要求...

  • 第四章多线程访问同步方法的7种情况

    1,两个线程同时访问一个对象的同步方法同步(互斥)执行2,两个线程访问的是两个对象的同步方法可同时执行3,两个线程...

  • 十二、Java高级特性(CAS基本原理)

    一、什么是原子操作?如何实现原子操作? 如果有两个操作A和B,分别有两个不同的线程执行。从A所在线程来看,执行B的...

  • iOS—多线程

    线程是用来执行任务的,线程彻底执行完任务A才能去执行任务B。为了同时执行两个任务,产生了多线程。 线程执行完毕就被...

  • 多线程同步

    目的: 多个线程同时运行 指定线程在其余线程执行完毕后继续执行 原理: 利用变量进行同步,变量的操作需要具有线程安...

网友评论

      本文标题:两个线程同时执行循环操作

      本文链接:https://www.haomeiwen.com/subject/axpouktx.html