volatile,多緒和最佳化

在多執行緒的情況下,考慮下面的程式碼 :

x =  0;
lock();
x++;
unlock();

一般來說,我們會認為有了 lock 和 unlock 的保護,變數 x 在多緒的環境下會被正常的累加。但如果我們把最佳化的影響考慮進來,情況就不如我們一開始所想的那麼地的單純。一般常見的最佳化做法如下:

  1. 編譯器為了提高變數 x  的存取速度而把 x 放到了某個 register 裡。
  2. 編譯器為了提高效率而交換指令執行的順序。
  3. CPU 的動態排程,為了提高效率而交換指令執行的順序。

以第一種情形來說,不同的執行緒的 register 是各自獨立的,若編譯器在 lock 之前就先把 x 放到 某個 register 裡,並因之後可能還要存取 x 而暫時不將 register 內的值寫回 x ,那麼很明顯就會有問題。針對編譯器過度最佳化的解決方法是使用關鍵字 volatile 提示編譯器考慮多緒執行的情況,不要進行如上的最佳化。

關鍵字 volatile 表示變數可能會被某些編譯器未知的因素更改 (如 I/O),所以每次要存取 volatile 變數時,必須從記憶體中重新讀取值。

而關於 3. CPU 的動態排程的影響,我們可以使用 CPU 所提供的 barrier 指令 (在不同 CPU 中指令名稱各不相同),來保證緒程安全。一般我們常使用的同步函式如 mutex 或 semaphore 等都有使用 barrier 來實作 。

Reference

0 意見 :: volatile,多緒和最佳化

張貼留言