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圖)java

image.png

按理說應該是這樣的啊安全

image.png

對,你想的沒錯,可是線程A,B的count值都等於3也是有可能的,下面咱們來分析下。多線程


詳細分析


對於代碼中45行,i--其實在JVM中,其實能夠分爲3步。jvm

  • 獲取count值(從主內存獲取值)
  • count減1(在各自寄存器完成)
  • 保存count(刷新到主內存)


詳細說下A,B實際上在機器中過程ide

  • 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圖>的執行過程。spa


結論


多線程安全一直是個很重要的話題,但願你們都能儘快理解掌握,但願你們喜歡!線程

我是叫練,多叫多練,歡迎你們和我一塊兒討論交流,我會盡快回復你們,喜歡點贊哦。3d

相關文章
相關標籤/搜索