close
前幾天剛好逛到幾篇說明 volatile 的文章,其中有關 volatile 在多執行緒環境的應用並不很完整,這裡做一點補充。
簡單來說,volatile 的作用僅僅是告訴編譯器不要用暫存器快取變數,每次使用都必須從資料的原始來源重新載入。
然而C語言並沒有規定 volatile 應該具備操作原子性,因此光使用 volatile 仍無助於解除 race condition。
以下面這段程式碼為例:
volatile int x = 0; // in thread x = x + 10;
在沒有 volatile 的情況下,編譯器會自動分析變數 x 的使用情形,只要條件許可,x 有機會在暫存器中歷經很長一段操作(例如一整個迴圈),中途不會重新讀取,也可能不會寫回。
而加了 volatile,只不過是每次使用都必須由記憶體重新存取而已。概念上機器指令會類似下面這樣,這裡假設 R1、R2 代表獨立的暫存器。
thread 1 | thread 2 |
---|---|
R1 <- x R1 <- R1 + 10 x <- R1 |
R2 <- x R2 <- R2 + 10 x <- R2 |
很明顯的,最後操作的結果仍舊取決於執行順序。有可能 thread 1 和 thread 2 同時取得 x,各自加上 10 並相繼寫回,那麼最後 x 只被加一次 10。也有可能 thread 2 所有操作都發生在 thread 1 寫回之後,那麼 x 會被加兩次 10。
無論如何,遇到 race condition 還是得配合真正的多緒存取控管機制,只使用 volatile 是不夠的。
全站熱搜
留言列表