案例


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

论断


多线程平安始终是个很重要的话题,心愿大家都能尽快了解把握,心愿大家喜爱!

我是叫练,多叫多练,欢送大家和我一起探讨交换,我会尽快回复大家,喜爱点赞哦。