Java 中的 volatile

文章最後更新於 2024 年 6 月 11 日

簡介

volatile 是 Java 中的一個關鍵字,用於修飾變數。它的主要作用是確保變數在多執行緒環境中的可見性和有序性。

主要特性

  1. 可見性:當一個變數被聲明為 volatile 時,對該變數的讀寫操作將直接反映在主記憶體中。這意味著一個執行緒對 volatile 變數的修改對其他執行緒立即可見。
  2. 有序性volatile 關鍵字還能防止指令重排序。這意味著在讀寫 volatile 變數時,不會將該操作與之前或之後的操作重新排序。

使用範例

以下是使用 volatile 關鍵字的範例:

public class VolatileExample {
    private volatile boolean flag = false;

    public void writer() {
        flag = true; // 寫操作
    }

    public void reader() {
        if (flag) {
            // 讀操作,能夠立即看到 flag 的變化
            System.out.println("Flag has been set to true");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileExample example = new VolatileExample();

        Thread writerThread = new Thread(example::writer);
        Thread readerThread = new Thread(example::reader);

        writerThread.start();
        writerThread.join(); // 確保 writerThread 完成

        readerThread.start();
        readerThread.join(); // 確保 readerThread 完成
    }
}

在這個範例中,flag 被聲明為 volatile。當 writerThread 設置 flagtrue 時,readerThread 能夠立即看到這個變化並輸出 “Flag has been set to true”。

volatile vs synchronized

特性volatilesynchronized
可見性
有序性
原子性是(對整個臨界區域)
性能高(適用於簡單的狀態標誌)低(可能導致阻塞)
使用場景簡單的狀態標誌,避免指令重排序複雜的邏輯和需要原子性操作的代碼區塊

適用場景

  • 狀態標誌:適用於簡單的 boolean 標誌,用於多執行緒之間的通信。
  • 單例模式(Double-Checked Locking):在雙重檢查鎖的實現中,用於標誌實例是否已經初始化。

不適用場景

  • 複雜的邏輯操作:如果變數需要複雜的邏輯操作(如增減),則應該使用 synchronized 來確保原子性。
  • 非原子性操作volatile 無法確保操作的原子性,例如 i++

注意事項

  • volatile 不適用於解決所有的並發問題。對於需要原子性操作的場景,應該使用更高級的同步機制(如 synchronizedLock)。

關於作者

卡哥
卡哥
我是Oscar (卡哥),前Yahoo Lead Engineer、高智商同好組織Mensa會員,超過十年的工作經驗,服務過Yahoo關鍵字廣告業務部門、電子商務及搜尋部門,喜歡彈吉他玩音樂,也喜歡投資美股、虛擬貨幣,樂於與人分享交流!

如果對文章內容有任何問題,歡迎在底下留言讓我知道。
如果你喜歡我的文章,可以按分享按鈕,讓更多的人看見我的文章。

網友留言