java 可見性簡單總結


Java 可見性

內存模型

  • 主存
    • 所有線程都可以訪問
  • 本地內存
    • 每個線程私有的內存
- java 的所有變量都存儲在主內存中
- 每個線程有自己獨的工作內存,保存了該線程使用到的變量副本,是對主內存中變量的一份拷貝
- 每個線程不能訪問其他線程的工作內存,線程間變量傳遞需要通過主內存來完成
- 每個線程不能直接操作主存,只能把主存的內容拷貝到本地內存后再做操作(這是線程不安全的本質),然后寫回主存

可見性的方法

volatile

這種方式可以保證每次取數直接從主存取

它只能保證內存的可見性,無法保證原子性

它不需要加鎖,比 synchronized 更輕量級,不會阻塞線程

不會被編譯器優化

然而要求對這個變量做原子操作,否則還是會有問題

雖然 volatile 是輕量級,但是它也需要保證 讀寫的順序不亂序,所以可以有優化點,比如在單例實現方式中的雙重校驗中,使用 臨時變量 降低 volatile 變量的訪問。

synchronized

Synchronized 能夠實現原子性和可見性;在 Java 內存模型中,synchronized規 定,線程在加鎖時,先清空工作內存 → 在主內存中拷貝最新變量的副本到工作內存 → 執行完代碼 → 將更改后的共享變量的值刷新到主內存中 → 釋放互斥鎖。

所以如果無法用 volatile 做可見性,則可以考慮用 synchronized 可以做可見性的保證

AtomicXXX

jdk 提供了很多原子類型,這種類型的基本原理總結起來,volatile + unsafe 的 Compare and Swap,這種 Unsafe 操作並不推薦在自己的代碼中使用,因為各 JDK 版本在這里變化較大,有可能升級 JDK 時造成各種問題。而且也要保證自己能夠用好。

LongAdder

待補充


免責聲明!

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



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