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


    案例


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

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

     

    结论


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

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

     

     

     

     

  • 相关阅读:
    浏览器开发者工具----F12 功能介绍
    python 爬虫之beautifulsoup(bs4)使用 --待完善
    python 爬虫之beautifulsoup(bs4)环境准备
    python dic字典使用
    python list的使用
    python 实现进制转换(二进制转十进制)
    字符串str的使用方法
    python 第一课 helloworld
    python 学习地址
    React中setState 什么时候是同步的,什么时候是异步的?
  • 原文地址:https://www.cnblogs.com/jiaolian/p/14145140.html
Copyright © 2020-2023  润新知