Java原子性、可見性、內存模型


原子性:

原子性就是指該操作是不可再分的。不論是多核還是單核,具有原子性的量,同一時刻只能有一個線程來對它進行操作。簡而言之,在整個操作過程中不會被線程調度器中斷的操作,都可認為是原子性。比如 a = 1;

非原子性:

也就是整個過程中會出現線程調度器中斷操作的現象

類似"a ++"這樣的操作不具有原子性,因為它可能要經過以下兩個步驟:

(1)取出 a 的值

(2)計算 a+1

如果有兩個線程t1,t2在進行這樣的操作。t1在第一步做完之后還沒來得及加1操作就被線程調度器中斷了,於是t2開始執行,t2執行完畢后t1開始執行第二步(此時t1中a的值可能還是舊值,不是一定的,只有線程t2中a的值沒有及時更新到t1中才會出現)。這個時候就出現了錯誤,t2的操作相當於被忽略了

類似於a += 1這樣的操作都不具有原子性。還有一種特殊情況,就是long跟double類型某些情況也不具有原子性,具體可參考:java中long和double類型操作的非原子性探究

 

共享變量:如果一個變量在多個線程的工作內存中都存在副本,那么這個變量就是這個幾個線程的共享變量

可見性:一個線程對共享變量值的修改,能夠及時的被其它線程看到。

    在多線程的情況下,共享變量不一定是可見的。要想實現變量的一定可見,可以使用synchronized、volatile兩種方式(其實還有final,但是它初始化后,值不可  更改,所以一般不用它實現可見性)。具體做法可參考:synchronized實現可見性volatile特性

 

Java內存模型(Java Memory Model) 描述了Java程序各種變量(線程共享變量)的訪問規則,以及在JVM中將變量存儲到內存和從內存中讀取出變量這樣的底層細節。

   在Java內存模型(以下簡稱為JMM)中:

  1) 所有的變量都存儲在主內存中

  2)每個線程都有自己獨立的工作內存,里面保存該線程使用到的變量的副本(主內存中該變量的一份拷貝)

   用下面的圖可以直觀的看到JMM中,線程、工作內存、主內存之間的關系:

  

    在上面的圖中,可以看到線程只與工作內存交互,不能直接訪問主內存。當主內存中有一個共享變量X,則工作內存則是將X拷貝,然后線程是操作工作內存中X的副本

    在JMM中,有兩條規定:

  1)線程對共享變量的所有操作都必須在自己的工作內存中進行,不能直接從主內存中讀寫

  2)不同線程之間無法訪問其他線程工作內存中的變量,線程間變量值的傳遞需要通過主內存來完成

    共享變量要實現可見性,必須經過如下兩個步驟:

  1)把工作內存1中更新過的共享變量刷新到主內存中

  2)把主內存中最新的共享變量的值更新到工作內存2中

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM