[英]Does as-if rule prevent compiler reordering of accesses to global/member variables?
我正在研究編譯器優化(特別是此處的指令重新排序)對多線程程序可能產生的影響。
假設我們有一個讀者線程和一個寫作者線程。
// Global shared data between threads
bool data;
bool flag = false;
// writer.cpp
void writer()
{
data = true; // (1)
flag = true; // (2)
}
// reader.cpp
void reader()
{
if (flag)
{
count << data;
}
}
可以使用符合C ++ 11的編譯器對指令(1)
和(2)
重新排序嗎?
根據C ++的“假設”規則,轉換不應更改程序的可觀察行為。 顯然,在編譯writer時,編譯器通常無法確定重新排序(1)
和(2)
是否會更改程序的可觀察行為,因為data
和flag
都是全局變量,可能會影響另一個線程的可觀察行為。
但它在此聲明可以發生這種重新排序,請參閱編譯時的內存排序 。
那么我們是否需要(1)
和(2)
之間的編譯器障礙? (我很清楚可能的CPU重新排序。這個問題僅適用於編譯器重新排序)
絕對可以。 編譯器沒有義務考慮其他線程或硬件的副作用。
僅當您使用volatile
或同步(並且二者不可互換)時,編譯器才被迫考慮這一點。
標准內存模型稱為SC-DRF,或順序一致數據競爭免費。 數據競爭正是您剛剛描述的情景 - 其中一個線程正在觀察非同步變量而另一個線程正在變異。 這是未定義的行為。 實際上,標准明確地賦予編譯器自由,假設沒有其他線程或硬件正在讀取非易失性非同步變量。 編譯器在此基礎上進行優化是絕對合法的。
順便說一下,該鏈接有點廢話。 他的“修復”並沒有解決任何問題。 多線程代碼的唯一正確解決方法是使用同步。
您已經在一周半前的comp.lang.c ++。mode中提出了這個問題,並且已獲得有關C ++ 11對單個線程內排序和“之前發生”的要求之間的關系的完整說明。線程之間的同步關系,請參見: https : //groups.google.com/forum/#!topic / comp.lang.c ++。moderated / 43_laZwVXYg
您不了解該回復的哪一部分,我們可以再試一次?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.