1. 程式人生 > >java基礎之Synchronized、volatile

java基礎之Synchronized、volatile

Synchronized

Synchronized語義

  1. 進入同步塊之前,先清空工作記憶體中的共享變數,從主記憶體中載入
  2. 解鎖之前(出去同步程式碼塊之前),必須把工作記憶體的共享變數 同步 到主記憶體**

Synchronized用法

  1. 物件鎖

  2. 類鎖

synchronized 影響記憶體的過程

  1. 一個執行緒在獲取到監視器鎖以後才能進入 synchronized 控制的程式碼塊
  2. 進入程式碼塊以後,該執行緒對於共享變數的快取就會失效,synchronized 程式碼塊中對於共享變數的讀取需要從主記憶體中重新獲取,也就能獲取到最新的值
  3. 退出synchronized 程式碼塊的時候的,會將該執行緒寫緩衝區中的資料刷到主記憶體中,所以說synchronized 具有可見性。
執行緒 a 對於進入 synchronized 塊之前或在 synchronized 中對於共享變數的操作,
對於後續的持有同一個監視器鎖的執行緒 b 可見

volatile

volatile 保證了可見性、禁止重排序,但是不能保證執行緒安全

volatile語義

  1. 使用volatile時,必須重新從主記憶體中載入,並且read、load是連續的
  2. 修改volatile修飾的變數後,必須立即同步主記憶體,並且store、write是連續的

volatile適用場景

  • 很明顯,計數器不適用,volatile 並不能保證原子性
  • Boolean的狀態標誌
  • 比如溫度檢測系統,一個執行緒定時從硬體讀取溫度,保證其他執行緒總是能拿到最新的問題
  • 一次性安全釋出(one-time safe publication),雙重檢查鎖定(double-checked-locking)問題

雙重檢查形式的單例模式為什麼需要使用 volatile

 private static SingletonTest instance = null;

    private int num;
    private SingletonTest() {
        this.num = 1;
    }

    public static SingletonTest getInstance() {
        if (instance == null)
{ // 1. 第一次檢查 synchronized (SingletonTest.class) { // 2 if (instance == null) { // 3. 第二次檢查 instance = new SingletonTest(); // 4 } } } return instance; }