我有一個多線程程序,主線程是第三方(無法更改它)和純C語言。我的任務是在它周圍建立新的模塊(使用C++),那些駐留部分在其他線程中,需要使用C程序的界面。基本上只是讀取一些在C線程中存儲和更新的變量(int,float,沒有什麼複雜的)。使用混合C和C++的線程同步
現在我的問題:我如何確保在訪問這些變量時不會因爲C界面而垃圾,因爲我無法在讀取時使用互斥鎖來鎖定它。這甚至有可能嗎?或者正在寫一個float/int原子操作呢?
我有一個多線程程序,主線程是第三方(無法更改它)和純C語言。我的任務是在它周圍建立新的模塊(使用C++),那些駐留部分在其他線程中,需要使用C程序的界面。基本上只是讀取一些在C線程中存儲和更新的變量(int,float,沒有什麼複雜的)。使用混合C和C++的線程同步
現在我的問題:我如何確保在訪問這些變量時不會因爲C界面而垃圾,因爲我無法在讀取時使用互斥鎖來鎖定它。這甚至有可能嗎?或者正在寫一個float/int原子操作呢?
你不能。讀寫任何東西都不是原子操作,如果你不能改變C代碼,那麼你運氣不好。同步化總是需要兩個部分被同步。
最好的辦法是要求第三方使他們的部分線程安全和/或與您共享鎖定機制。
你不能。在這種情況下工作的唯一正確方法是隻使用調用C線程提供給函數的參數 - 而不是之後存儲對它們的引用。沒有辦法保證任何變量不會被修改 - 一般情況下。
您需要重新考慮您的架構,以免出現這種需求。
如果您無法確定設置變量值的代碼是否同步,則在讀取時放置一個鎖是沒有意義的,並且不起作用。這不僅是操作的原子性,也是數據可見性 - 對這些變量的更新可能對其他線程不可見。
如果你控制主線程,你必須爲你必須訪問的每個人創建一個新變量,從主線程訪問它,並使用鎖定,設置新創建的變量的值。然後,從其他線程訪問只有那些同步變量。
int myVal = 0;
int main() {
while(!shouldQuit()) {
doSomeIndependentStuff();
pthread_lock(&mutex);
myVal = independentGlobalVal;
pthread_unlock(&mutex);
}
}
int getMyVal() {
int retVal = 0;
pthread_lock(&mutex);
retVal = myVal;
pthread_unlock(&mutex);
return retval;
}
語句如「寫入float/INT [是]一個原子操作反正」的,不幸的是,不能很好地在C或C++中定義(儘管與C++ 11和stdatomic使用std::atomic
。 h的方法可以在這裏幫助 - 但這不會幫助你用C interop來創建一個你不能修改的庫,所以你可以在這裏忽略它)。
您可以在特定的編譯器和平臺上找到有關這些問題的指導 - 例如,您可能會發現在大多數平臺上,如果對齊,對齊的32位或64位讀取或寫入將是原子的,大多數編譯器會適當地調整它們。
但是,在這條路上走的是瘋狂。如果您涉及多個線程,只需使用POSIX/pthreads功能(如可從C和C++輕鬆訪問的pthreads mutexes)來防止跨線程共享狀態的任何訪問。
由於您無法修改C代碼,因此您可能必須在C++代碼中進行所有鎖定,然後才能調用C庫,然後解鎖。如果你可以閱讀,但不能修改C代碼,或者文檔對線程/共享模型非常清楚,你可以使用細粒度的鎖定策略,但是如果沒有任何分析表明存在瓶頸, d首先使用一個全局鎖來防止對C API的每次訪問。
混合C/C++與問題無關。我建議調用這個線程「與外部庫的數據同步」或類似的東西。 – Dariusz
什麼CPU和操作系統?我認爲這會影響到什麼是原子,什麼不是。另外,你總是會遇到緩存問題,也就是說其他線程已經改變了值,但是它還沒有寫入主RAM,所以你最好不要做任何有點過時的問題,這是一個致命的問題。 – hyde
這就是我想的......我不想讓它依賴於某種特殊的架構。 – fewu