Java并发之volatile
生活随笔
收集整理的這篇文章主要介紹了
Java并发之volatile
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1:概念
- 2:解決的問題
- 3:可見性
- (1):問題的引出
- (2):如何解決
- (3):拓展
- 4:有序性
- (1):問題的引出---指令重排
- (2):如何解決指令重拍呢
- 5:volatile原理
- (1):內存屏障
- (2):如何保證可見性呢
- (3):如何保證有序性呢
1:概念
JMM即Java Memory Model,它定義了主存、工作內存抽象概念,底層對應著CPU寄存器、緩存、硬件內
存、CPU指令優化等。
2:解決的問題
JMM體現在以下幾個方面
- 原子性-保證指令不會受到線程上下文切換的影響(比如說是n++,如果發生線程上下文切換的話,那就破壞了這一條指令的執行)
- 可見性-保證指令不會受cpu緩存的影響
- 有序性-保證指令不會受cpu指令并行優化的影響
3:可見性
(1):問題的引出
可見性是指一個線程對一個變量進行修改,另外一個線程可以看的到
可見性問題是由CPU的緩存導致的,多核CPU均有各自的緩存,這些緩存要與內存進行同步。(其實就是多線程環境下,一個線程對一個變量的改變了,而另一個線程沒看到,那么的話還是按照原來的變量的值進行計算的話,那么就會出錯)。
(2):如何解決
我們可以對該變量加上 volatile 關鍵字,這樣的話,每次線程都是從主存中去取變量,這樣就解決了緩存中數據與主存中數據不一致的問題。我們也可以使用關鍵字 synChronized 關鍵字來進行解決可見性問題,只不過synChronized是重量級鎖,會影響性能。
(3):拓展
- volatile適合在一個寫線程和多個讀線程中使用,只能保證變量在內存中的可見性,并不能防止上下文切換帶來的原子性問題。
- 但是對變量加上 volatile關鍵字并不能接解決 原子性問題;但終歸還得是靠老大哥synChronized來上鎖,既能防止上下文切換解決原子性問題,也可以解決變量可見性問題。
4:有序性
(1):問題的引出—指令重排
為什么會有指令重拍呢,主要是CPU進行優化,提高處理速度造成的。一條指令可以分為 取指令·指令譯碼·執行指令·內存訪問·數據寫回 CPU可以在一個時鐘周期內,執行不同指令中的不同階段,也就是同時將5條指令同時進行中,那么其實這樣的話,就會出現指令重排問題,因為在一個CPU時鐘周期內,我們執行的不是一條完整的指令。
(2):如何解決指令重拍呢
主要也是在相關變量上加上 volatile關鍵字
5:volatile原理
(1):內存屏障
- volatile的底層實現原理是內存屏障,Memory Barrier(Memory Fence)
- 對volatile變量的寫指令后會加入寫屏障
- 對volatile變量的讀指令前會加入讀屏障
(2):如何保證可見性呢
- 寫屏障:保證在該屏障之前的,對共享變量的改動都同步到主內存中
- 讀屏障:保證在該屏障之后,對共享變量的讀取,加載的是主存中最新數據
(3):如何保證有序性呢
- 寫屏障會確保指令重排序時,不會將寫屏障之前的代碼排在寫屏障之后
- 讀屏障會確保指令重排序時,不會將讀屏障之后的代碼排在讀屏障之前
- 其實也就是有了內存屏障,那么就有了有序性。
總結
以上是生活随笔為你收集整理的Java并发之volatile的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 漫谈硬盘彻底损坏后的数据抢救
- 下一篇: Excel单元格内如何添加多条斜线并添加