案例


 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图>的执行过程。

结论


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

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

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

Java中多线程安全问题实例分析的更多相关文章

  1. Java中多线程的使用(超级超级详细)线程池 7

    Java中多线程的使用(超级超级详细)线程池 7 什么是线程池? 线程池是一个容纳多个线程的容器,线程池中的线程可以重复使用,无需反复创建线程而消耗过多的资源 *使用多线程的好处: 1.降低消耗,减少 ...

  2. Java中多线程的使用(超级超级详细)线程安全原理解析 4

    Java中多线程的使用(超级超级详细)线程安全 4 什么是线程安全? 有多个线程在同时运行,这些线程可能会运行相同的代码,程序运行的每次结果和单线程运行的结果是一样的,而且其他变量的值也和预期的值一样 ...

  3. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  4. 2.1多线程(java学习笔记) java中多线程的实现(附静态代理模式)

    一.多线程 首先我们要清楚程序.进程.线程的关系. 首先进程从属于程序,线程从属于进程. 程序指计算机执行操作或任务的指令集合,是一个静态的概念. 但我们实际运行程序时,并发程序因为相互制约,具有“执 ...

  5. 关于java中构造方法、实例初始化、静态初始化执行顺序

    在Java笔试中,构造方法.实例初始化.静态初始化执行顺序,是一个经常被考察的知识点. 像下面的这道题(刚刚刷题做到,虽然做对了,但是还是想整理一下) 运行下面的代码,输出的结果是... class ...

  6. java中多线程执行时,为何调用的是start()方法而不是run()方法

    Thead类中start()方法和run()方法的区别 1,start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状 ...

  7. Java中ArrayList源码分析

    一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...

  8. Java 中线程安全问题

    不好意思,一个国庆假期给我放的都不知道东西南北了,放松,很放松,差一点就弃更了,感谢那些催更的小伙伴们! 虽然没有更新,但是日常的学习还是有的,以后我尽量给大家分享一些通用知识,非技术. 但是本期还是 ...

  9. Java并发/多线程-CAS原理分析

    目录 什么是CAS 并发安全问题 举一个典型的例子i++ 如何解决? 底层原理 CAS需要注意的问题 使用限制 ABA 问题 概念 解决方案 高竞争下的开销问题 什么是CAS CAS 即 compar ...

随机推荐

  1. 【转】Java工程师知识图谱

    一.Java工程师知识图谱(思维导图版) 二.Java工程师知识图谱(文字链接版) 专业基石 数据结构 数组 链表 队列 栈 哈希表 堆 树 图 BitMap 算法思想 排序 查找 分支算法 动态规划 ...

  2. FL Studio中有关减少CPU占用率的一些技巧

    在使用FL Studio20进行音乐制作时经常容易碰到的工程卡顿,声音延迟现象绝大部分是由于电脑CPU超负荷运行而导致的.除了提升电脑本身的性能以外,在FL Studio20中我们也可以运用一些方法来 ...

  3. try...catch的前世今生

    1975年, John Goodenough发表论文,提出异常处理的建议: 一是明确声明命令可能抛出何种异常: 二是需要有将可能出错的操作括起来的语句结构. Communications of the ...

  4. 【python】Matplotlib作图中有多个Y轴

    在作图过程中,需要绘制多个变量,但是每个变量的数量级不同,在一个坐标轴下作图导致曲线变化很难观察,这时就用到多个坐标轴.本文除了涉及多个坐标轴还包括Axisartist相关作图指令.做图中label为 ...

  5. dubbo起停之服务暴露

    由上一节可知带上dubbo@Service注解的对象,在注册成为bean之后会进一步注册一个ServiceBean,服务暴露便是在这里 public void afterPropertiesSet() ...

  6. django中的积累

    只要继承了model.Model, 就会生成一个新的表,但是,如果在Meta方法中添加abstract=True,就不会产生新的表,而是作为一个基类存放多个表共同拥有的方法和字段等 from djan ...

  7. 手撕HashMap

    前言: 平时工作的时候,用的最多的就是ArrayList和HashMap了,今天看了遍HashMap的源码,决定自己手写一遍HashMap. 一.创建MyHashMap接口       我们首先创建一 ...

  8. Springboot结合Jpa的外键使用

    当我们写项目的时候,总有些奇奇怪怪的理由,非让你连表查询,其实最好的就是什么都不连,数据库完全解耦 但我们还是要学习下Jpa怎么根据外键查询 (这里说下Jpa+springboot的感觉,刚开始就感觉 ...

  9. 写给程序员的机器学习入门 (十) - 对象识别 Faster-RCNN - 识别人脸位置与是否戴口罩

    每次看到大数据人脸识别抓逃犯的新闻我都会感叹技术发展的太快了,国家治安水平也越来越好了

  10. 记一次容器CPU高占用问题排查

    起因:发现docker中有两个容器的CPU持续在百分之95以上运行了一晚上 执行命令:docker stats 发现这个两个大兄弟一点没歇满负荷跑了一晚上,再这么下去怕不是要GG 容器里跑的是JAVA ...