2017-08-13 125 views
0

問題很簡單。 是否/應該在多線程中使用的變量是volatile,甚至在C中的關鍵部分(即互斥量,信號量)中被訪問?爲什麼/爲什麼不?帶互斥量和信號量的volatile關鍵字

#include <pthread.h> 

    volatile int account_balance; 
    pthread_mutex_t flag = PTHREAD_MUTEX_INITIALIZER; 

    void debit(int amount) { 
    pthread_mutex_lock(&flag); 
    account_balance -= amount;//Inside critical section 
    pthread_mutex_unlock(&flag); 
} 

這個例子或等價的信號量思考怎麼樣?

+0

https://stackoverflow.com/a/78221/635608 – Mat

+0

爲什麼/爲什麼不呢? @Mat – concurrencyboy

+0

你想讓我重新鍵入英特爾在這裏鏈接的文章嗎?或重新輸入其他答案? – Mat

回答

1

是否應該在多線程中使用的變量在C中的臨界區(即互斥量,信號量)中是易變的?爲什麼/爲什麼不?

volatile是併發性邏輯無關,因爲它不足夠

其實,這是不是真的 - volatile不無關係,因爲它可以在你的代碼隱藏併發問題,所以它的工作原理「大部分時間」。

所有揮發性所做的就是告訴編譯器「這個變量可以執行的當前線程外部改變」。揮發性決不會強制執行任何順序,原子性或 - 關鍵 - 可視性。正因爲線程2 CPU A改變int x,這並不意味着在CPU d線1甚至可以看到在任何特定時間的變化 - 它有它自己的緩存值,並volatile意味着幾乎對於任何內存的一致性,因爲它不保證排序。

在英特爾文章揮發性底部的最後註釋:Almost Useless for Multi-Threaded Programming最好說它:

如果您只是添加「揮發」到被線程以爲之間共享 變量解決您的共享數據問題沒有 困擾,爲什麼它可能不會,你最終會收穫你應得的回報。

是的,無鎖碼可以利用volatile。此類代碼由可能編寫關於使用volatile,多線程代碼以及其他有關編譯器的非常詳細主題的教程編寫。

1

不,volatile不應該用於在pthreads同步函數保護下訪問的共享變量,如pthread_mutex_lock()

原因在於POSIX提供的同步功能本身可以提供所有必要的編譯器障礙和同步以確保一致性(只要您遵循POSIX關於併發訪問的規則 - 即您已經使用了pthreads同步函數以確保在另一個線程正在寫入或從中讀取數據時,沒有線程可以寫入共享變量)。