案例
package com.duyang.thread.basic.basethread;
/**
* @author:jiaolian
* @date:Created in 2020-12-16 14:02
* @description:线程不平安剖析
* @modified By:* 公众号: 叫练
*/
public class ThreadUnsafe {public static void main(String[] args) {Thread task = new Task();
Thread threadA = new Thread(task,"A");
Thread threadB = new Thread(task,"B");
Thread threadC = new Thread(task,"C");
Thread threadD = new Thread(task,"D");
Thread threadE = new Thread(task,"E");
threadA.start();
threadB.start();
threadC.start();
threadD.start();
threadE.start();}
private static class Task extends Thread {
int count = 5;
@Override
public void run() {
/**
* jvm 分 3 步骤;
* 1. 获取 count(从主内存获取值)
* 2.count 减 1(在各自寄存器实现)
* 3. 保留 count(刷新到主内存)
*
* 说下可能执行的过程...
* A 线程获取 cpu 的 count 值为 5,A 线程先减去 1,保留 count 值为 4 刷新到主内存, 此时还没有执行 System.out.println count
* 切换到 B 线程,此时 B 线程的 count 值为 4,因为 B 线程是从主内存取的,B 线程 count 值减去 1 为 3,此时刷新到主内存,主内存值变为 3
* 切换到 A 线程,执行 System.out.println count=3
* 切换到 B 线程,执行 System.out.println count=3
* 状况就是这样的
*
*/
count--;
System.out.println(Thread.currentThread().getName() + " "+count);
}
}
}
可能的后果
后果失去下图(论断 1 图)
按理说应该是这样的啊
对,你想的没错,然而线程 A,B 的 count 值都等于 3 也是有可能的,上面咱们来剖析下。
详细分析
对于代码中 45 行,i– 其实在 JVM 中,其实能够分为 3 步。
- 获取 count 值(从主内存获取值)
- count 减 1(在各自寄存器实现)
- 保留 count(刷新到主内存)
具体说下 A,B 实际上在机器中过程
- A 线程获取 cpu 的 count 值为 5,A 线程先减去 1,保留 count 值为 4 刷新到主内存, 此时还没有执行 System.out.println 打印 count 值。如下图所示
- 切换到 B 线程,此时 B 线程的 count 值为 4,因为 B 线程是从主内存取的,B 线程 count 值减去 1 为 3,此时刷新到主内存,主内存值变为 3
- 切换到 A 线程,执行 System.out.println count=3
- 切换到 B 线程,执行 System.out.println count=3
- C D E 线程失常执行
这就是 < 论断 1 图 > 的执行过程。
论断
多线程平安始终是个很重要的话题,心愿大家都能尽快了解把握,心愿大家喜爱!
我是叫练,多叫多练,欢送大家和我一起探讨交换,我会尽快回复大家,喜爱点赞哦。