1. 程式人生 > >JMM與併發相關的三個特性:原子性、可見性和有序性

JMM與併發相關的三個特性:原子性、可見性和有序性

一、原子性(Atomicity)
由Java記憶體模型來直接保證的原子性變數操作包括read、load、assign、use、store和write這六個,我們大致可以認為基本資料型別的訪問讀寫是具備原子性的,如果應用場景需要一個更大範圍的原子性保證,Java記憶體模型還提供了lock和unlock操作來滿足這種需求,儘管虛擬機器未把lock和unlock操作直接開放給使用者使用,但是卻提供了更高層次的位元組碼指令monitorenter和monitorexit來隱式地使用這兩個操作,這兩個位元組碼指令反映到Java程式碼中就是同步快-synchronized關鍵字,因此synchronized塊之間的操作也具備原子性。
二、可見性(Visibility)
可見性就是指當一個執行緒修改了共享變數的值,其他執行緒能夠立即得知這個修改。Java記憶體模型是通過在變數修改後將新值同步回主記憶體,在變數讀取前從主記憶體重新整理變數值這種依賴主記憶體作為傳遞媒介的方式來實現可見性的,無論是普通變數還是volatile變數都是如此,普通變數與volatile變數的區別是volatile的特殊規則保證了新值能立即同步到主記憶體,以及每次使用前立即從主記憶體重新整理。因此我們可以說volatile保證了多執行緒操作時變數的可見性,而普通變數則不能保證這一點。
除了volatile之外,Java還有兩個關鍵字能實現可見性,它們是synchronized和final。同步快的可見性是由“對一個變數執行unlock操作之前,必須先把此變數同步回主記憶體中(執行store和write操作)”這條規則獲得的,而final關鍵字的可見性是指:被final修飾的欄位在構造器中一旦初始化完成,並且構造器沒有把this的引用傳遞出去(this引用逃逸是一件很危險的事情,其他執行緒有可能通過這個引用訪問到初始化了一半的物件),那麼在其他執行緒中就能看見final欄位的值。

三、有序性(Ordering)
Java記憶體模型的有序性是指如果在本執行緒內觀察,所有操作都是有序的;如果一個執行緒中觀察另一個執行緒,所有的操作都是無序的。前一句是指執行緒內表現為序列的語義,後一句是指指令重排序現象和工作記憶體與主記憶體同步延遲的現象。
Java語言提供了volatile和synchronized兩個關鍵字來保證執行緒之間操作的有序性,volatile關鍵字本身就包含了禁止指令重排序的語義,而synchronized則是由“一個變數在同一時刻只允許一條執行緒對其進行lock操作”這條規則獲得的,這個規則決定了持有同一個鎖的兩個同步塊只能序列地進入。