volatile关键字的作用-适用场景
volatile在Java并發編程中常用于保持內存可見性和防止指令重排序。內存可見性(Memory Visibility):所有線程都能看到共享內存的最新狀態;防止指令重排:在基于偏序關系的Happens-Before內存模型中,指令重排技術大大提高了程序執行效率,但同時也引入了一些問題。
volatile保持內存可見性的特殊規則:read、load、use動作必須連續出現;assign、store、write動作必須連續出現;每次讀取前必須先從主內存刷新最新的值;每次寫入后必須立即同步回主內存當中。
也就是說,volatile關鍵字修飾的變量看到的隨時是自己的最新值。在線程1中對變量v的最新修改,對線程2是可見的。
volatile防止指令重排的策略:在每個volatile寫操作的前面插入一個StoreStore屏障;在每個volatile寫操作的后面插入一個StoreLoad屏障;在每個volatile讀操作的后面插入一個LoadLoad屏障;在每個volatile讀操作的后面插入一個LoadStore屏障。
注意:只有在Happens-Before內存模型中才會出現這樣的指令重排序問題。
?
1.volatile最適用一個線程寫,多個線程讀的場合。
? ?如果有多個線程并發寫操作,仍然需要使用鎖或者線程安全的容器或者原子變量來代替。(摘自Netty權威指南)
? ?疑問:如果只是賦值的原子操作,是否可以多個線程寫?(答案:可以,但是一般沒有這樣的必要,即沒有這樣的應用場景)
?
最經典的使用案例:
volatile boolean shutdownRequested;...public void shutdown() { shutdownRequested = true; }public void doWork() { while (!shutdownRequested) { // do stuff} }?
使用場景2:
結合使用 volatile 和 synchronized 實現 “開銷較低的讀-寫鎖”
volatile 允許多個線程執行讀操作,因此當使用 volatile 保證讀代碼路徑時,要比使用鎖執行全部代碼路徑獲得更高的共享度 —— 就像讀-寫操作一樣。
?
public class CheesyCounter {private volatile int value;public int getValue() { return value; }public synchronized int increment() {return value++;} }?
或者
private volatile long start = System.currentTimeMillis();public synchronized long get() {return start++;}?
正確使用 volatile 變量的條件
您只能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:
- 對變量的寫操作不依賴于當前值。
- 該變量沒有包含在具有其他變量的不變式中。
更多使用場景可參考:
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
總結
以上是生活随笔為你收集整理的volatile关键字的作用-适用场景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 聚飞转债(370303)什么时候发行?不
- 下一篇: 频繁申请信用卡会影响贷款吗