写点什么

Java 中多线程安全问题实例分析

用户头像
叫练
关注
发布于: 2020 年 12 月 16 日
Java中多线程安全问题实例分析

案例




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图)



image.png



按理说应该是这样的啊



image.png



对,你想的没错,但是线程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值。如下图所示



image.png



  • 切换到B线程,此时B线程的count值为4,因为B线程是从主内存取的,B线程count值减去1为3,此时刷新到主内存,主内存值变为3



image.png



  • 切换到A线程,执行System.out.println count=3

  • 切换到B线程,执行System.out.println count=3

  • C D E线程正常执行



这就是<结论1图>的执行过程。



结论


多线程安全一直是个很重要的话题,希望大家都能尽快理解掌握,希望大家喜欢!

我是叫练,多叫多练,欢迎大家和我一起讨论交流,我会尽快回复大家,喜欢点赞哦。



发布于: 2020 年 12 月 16 日阅读数: 12
用户头像

叫练

关注

还未添加个人签名 2020.06.11 加入

还未添加个人简介

评论

发布
暂无评论
Java中多线程安全问题实例分析