首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多線程基礎總結(三):volatile 關鍵字與輕量級同步

     編輯:Java 相關知識

volatile 被譽為「輕量級的 synchronized」,但**僅保證可見性,不保證原子性**。濫用會導致並發 Bug,必須精準把握適用場景。

底層實現與語義

  • **禁止寄存器緩存**:寫入後立即刷回主內存;讀取時強制從主內存加載。
  • **禁止指令重排序**:確保 volatile 變量與普通變量的讀寫順序不被 JVM/CPU 優化打亂。

核心限制:無法保證「讀-改-寫」原子性

i++、flag = !flag 等複合操作,**即使加 volatile 仍不安全**。

// 錯誤示範:檢查-設置非原子
private volatile boolean flag;
if (!flag) { flag = true; } // 多線程下可能多次進入

正確使用條件

  1. 寫入**不依賴當前值**(單純賦值、一次性初始化)。
  2. **多讀少寫**場景,配合 synchronized 實現「讀寫分離」:
public class AnotherSyncSample {
    private volatile int counter; // 讀取無鎖,極快
    public int getCounter() { return counter; }
    public synchronized void add() { counter++; } // 寫入加鎖保證原子性
}

重排序防護實例

class VolatileSample {
    private volatile boolean finished;
    private int lucky;

    public void doSomething() {
        if (finished) System.out.println("lucky: " + lucky); // 讀到 finished=true 時,lucky 必為 7
    }
    public void finish() {
        lucky = 7;
        finished = true; // volatile 禁止 lucky=7 後於 finished=true 重排
    }
}

無 volatile 時,JVM 可能先寫 finished=true 再寫 lucky=7,導致另一線程讀到 finished=true 但 lucky=0。

總結

  • volatile 適合**狀態標記**、**一次性發布**、**獨立觀察**場景。
  • 複雜邏輯請用 synchronized、Lock 或 atomic。
  • 理解「可見性 ≠ 原子性」是並發編程的分水嶺。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved