案例


 1 package com.duyang.thread.basic.basethread;
2
3 /**
4 * @author :jiaolian
5 * @date :Created in 2020-12-16 14:02
6 * @description:线程不安全分析
7 * @modified By:
8 * 公众号:叫练
9 */
10 public class ThreadUnsafe {
11
12 public static void main(String[] args) {
13 Thread task = new Task();
14 Thread threadA = new Thread(task,"A");
15 Thread threadB = new Thread(task,"B");
16 Thread threadC = new Thread(task,"C");
17 Thread threadD = new Thread(task,"D");
18 Thread threadE = new Thread(task,"E");
19 threadA.start();
20 threadB.start();
21 threadC.start();
22 threadD.start();
23 threadE.start();
24 }
25
26 private static class Task extends Thread {
27
28 int count = 5;
29 @Override
30 public void run() {
31 /**
32 * jvm分3步骤;
33 * 1.获取count(从主内存获取值)
34 * 2.count减1(在各自寄存器完成)
35 * 3.保存count(刷新到主内存)
36 *
37 * 说下可能执行的过程...
38 * A线程获取cpu的count值为5,A线程先减去1,保存count值为4刷新到主内存,此时还没有执行System.out.println count
39 * 切换到B线程,此时B线程的count值为4,因为B线程是从主内存取的,B线程count值减去1为3,此时刷新到主内存,主内存值变为3
40 * 切换到A线程,执行System.out.println count=3
41 * 切换到B线程,执行System.out.println count=3
42 * 情况就是这样的
43 *
44 */
45 count--;
46 System.out.println(Thread.currentThread().getName() + " "+count);
47 }
48 }
49 }
 

可能的结果


结果得到下图(结论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图>的执行过程。

结论


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

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

 
  • 清除所有标记
  • 清除选中的标记
  • 错误类型
  • 无错字 - 写作(在线版)
 
 

最新文章

  1. webapi - 使用依赖注入
  2. ES6新特性概览
  3. centos 6.4 getmail 收取163 邮件
  4. proxy改变this指向
  5. Asp.net 执行回调操作后 无法更新ViewState的问题
  6. spring与mysql整合数据源的配置
  7. python3 sys模块
  8. Java中数据类型默认转换和强制类型转换
  9. Collection接口中方法的使用
  10. one by one 项目 part 3
  11. testlink问题--linux环境下
  12. 使用方法拦截机制在不修改原逻辑基础上为 spring MVC 工程添加 Redis 缓存
  13. QQ窗体的控制,同步异步打开360网盘,控制360网盘窗体的移动
  14. js鼠标触发事件集合
  15. Light oj 1379 -- 最短路
  16. C# 笔记——数据类型
  17. Django-内置Admin
  18. php与js的crc32(支持中文)
  19. LVS + KEEPALIVED + WINDOWS SERVER 2008 R2 ------高可用负载均衡(转)
  20. Zookeeper用来干什么?

热门文章

  1. phpmyadmin远程代码执行漏洞(CVE-2016-5734)
  2. python-基础入门-序
  3. 插件SimSynth合成器功能介绍
  4. 对于this和当前线程的一些理解
  5. Codeforces Round #674 (Div. 3) C、D 题解
  6. 小叶入门之Python爬虫(一)
  7. java46
  8. java45
  9. Spring Cloud Alibaba 初体验(六) Seata 及结合 MyBatis 与 MyBatis-Plus 的使用
  10. vue中全局/按需引用element,样式都不生效