java并发多线程执行顺序问题

问题描述

提示:这里描述项目中遇到的问题:

在学习并发编程过程中,发现多线程的执行顺序可能会导致运行结果的不同。

// a为初始值为1的共享变量,这里如果thread2先执行,则程序可以正常退出,thread先执行,程序阻塞
	@Test
    public void test2() throws InterruptedException {
        Thread thread2 = new Thread(() -> {
            System.out.println("start change");
            flag = true;
            a = 2;
            System.out.println(flag);
            System.out.println("end change");
        });
        thread2.start();
        Thread.sleep(1000);
        Thread thread = new Thread(() -> {
            System.out.println("start....");
            int cnt = 0;
            while (a==1){
            }
            System.out.println("a="+a);
            System.out.println("cnt:"+cnt);
            System.out.println("end....");
        });
        thread.start();
    }

原因分析:

这里基于JMM内存模型进行分析
Thread2先执行的情况:

  1. Thread2执行到a=2这条指令,将主内存中的变量a经过总线加载到线程内部的工作内存,即此时Thread2的工作内存中,有这个变量a的副本,此时a=1。
  2. Thread2执行a=2,底层通过赋值命令将工作内存中的变量a的值修改为2,同时再通过总线发送指令,将主内存中的a修改为2
  3. Thread2执行完毕后,Thread1执行循环,这里就直接读取了主内存中的a(因为此时Thread1线程的工作内存中,没有a的副本,需要从主内存中load),之后执行跳出循环,程序结束

Thread1先执行的情况:

  1. Thread1先从主内存中load对应的a变量,在工作内存中创建副本,放在线程内部寄存器的缓存行中,此时缓存的a=1,进入循环。
  2. Thread2读取、修改、返回a=2,此时主内存中的a为2。
  3. 由于Thread1中寄存器中a对应的缓存行仍然是有效状态,Thread1无法得知主内存中的a已经改变,因此进入死循环。

小结:

  • 线程的运行顺序会对程序造成影响。
  • 在进行多线程并发编程时,尽量避免使用System.out.println进行打印,println底层使用synchronized关键字加锁打印,使得类被加锁,保证了可见性、有序性以及原子性。
  • 在Thread1先运行的情况下,如果要使程序正常运行,可以对变量a加上volatile进行修饰,底层通过缓存一致性协议、禁止指令重排序、总线嗅探判断缓存行是否失效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值