java-多線程深入(四)Volatile分析,java-volatile

來源:互聯網
上載者:User

java-多線程深入(四)Volatile分析,java-volatile

(一)volatile的使用

1、使用情境

(1)狀態標識。用於即時指示某個重要性事件的發生,比如完成初始化或者停機。

volatile boolean toShutdown;    ......    public void shutdown() { toShutdown = true; }    public void doWork() {         while (!toShutdown) {             // 執行操作        }    }
(2)對象安全發布。volatile是處理對象安全發布的其中一種方式,更多內容參加這裡。
class Singleton{        private volatile static Singleton instance = null;                 private Singleton() {                     }                 public static Singleton getInstance() {            if(instance==null) {                synchronized (Singleton.class) {                    if(instance==null)                        instance = new Singleton();                }            }            return instance;        }    }

經典的雙重檢查單例模式,volatile變數不會導致new對象的時候對象未初始化完成。

2、通常來說,使用volatile必須具備以下2個條件:
(1)對變數的寫操作不依賴於當前值
(2)該變數沒有包含在具有其他變數的不變式中

對於1,因為volatile變數不保證原子性,一個線程執行i++的同時另一個線程擷取i的值,不一定能擷取到最新值。

對於2,

    volatile int min = 0;    volatile int max = 10;    public boolean setA(int newMin) {        if (newMin > max) {            return false;        }        min = newMin;        return true;    }        public boolean setB(int newMax) {        if (newMax < min) {            return false;        }        max = newMax;        return true;    }
一個線程調用setA(8),一個線程調用setB(2),可能會得到min=8、max=2,這與最初代碼設計意圖不符合。


(二)原理分析

volatile實現記憶體可見度原理:

volatile Singleton instance = new Singleton();

instance變數在進行寫操作的時候,彙編下增加了lock指令。

lock指令的作用:

1.線程工作記憶體中的資料在進行寫操作的時候,會立即回寫到主記憶體中

2.回寫到主記憶體時,讓其他CPU中該資料的緩衝失效,下次讀取需要重新從主記憶體中擷取

/** * Volatile的使用測試 * * @author peter_wang * @create-time 2015-1-14 下午10:11:57 */public class ThreadVolatileDemo {    private boolean isStop = false;    private void changeStatus() {        isStop = !isStop;    }    /**     * @param args     */    public static void main(String[] args) {        final ThreadVolatileDemo test = new ThreadVolatileDemo();        Thread thread1 = new Thread() {            @Override            public void run() {                System.out.println("嘗試退出開始");                while (true) {                    //一直檢測isStop變數是否更新                    if (test.isStop) {//A1                        System.out.println("退出成功");                        System.exit(0);                    }                }            }        };        thread1.start();        try {            Thread.sleep(3000);            test.changeStatus();        }        catch (InterruptedException e) {            e.printStackTrace();        }    }}
A1部分不斷迴圈重複讀取isStop值,但是讀取的是線程工作記憶體中的資料,而且不斷命中該資料,資料區塊不易被替換,增加讀取到舊值的機率。修改isStop變數為volatile,變數被修改後會立即回寫到主記憶體,A1讀取線程工作記憶體失效,從主記憶體中讀取到最新值。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.