[英]Is a comparison an atomic operation?
以下比較是原子動作嗎? 即,它可以簡化為單個CPU指令嗎?
char flag = 2;
for(;;)
{
if (!flag) // <-- this
break;
// sleep
}
這是我正在做的事情:
int main()
{
sf::Mutex Mutex;
char flag = 2;
coordinatorFunction(flag);
for(;;)
{
if (!flag)
break;
// sleep
}
}
void workerFunction(void* a)
{
char* p = static_cast<char*>(a);
// work
GlobalMutex.Lock();
--*p;
GlobalMutex.Unlock();
}
void coordinatorFunction(char& refFlag)
{
sf::Thread worker1(&workerFunction, &refFlag);
sf::Thread worker2(&workerFunction, &refFlag);
worker1.Launch();
worker2.Launch();
}
這是錯誤的方法。
你的主線程盡可能快地燒掉CPU周期,除了等待flag
達到零之外什么都不做。 除了最后一次測試外,每次嘗試都會失敗。 而不是以這種方式執行它,使用您的線程對象最有可能必須使“主要線程暫停”的“連接”工具,直到所有工作人員完成。
這樣, 並非巧合的是 ,你不會關心測試是否是原子的,因為你根本不需要它。
C ++操作都不能保證是原子操作。
在C ++中,沒有任何東西可以保證是原子的。
不,C ++不保證任何操作都是原子的。 你的問題中的代碼很可能被編譯成從內存到寄存器的加載,這可能本身需要多個指令,然后是測試。
比較不是原子的,因為它需要幾個機器語言指令來執行它(從內存加載到寄存器等)。由於內存模型的靈活性和緩存,執行測試的線程可能無法“看到”另一個線程的結果馬上。
如果變量標記為volatile,則可能安全地進行簡單測試,但這將是特定於平台的。 正如其他人所說,C ++本身並不能保證這一點。
不 。
比較涉及讀取兩個數據以及執行實際比較。 數據可以在讀取和比較指令之間變化 ,因此它不是原子的。
但是,因為您正在比較相等性,所以_InterlockedCompareExchange
(對於x86中的lock cmp xchg
指令)可能會執行您所需的操作,盡管它將涉及替換數據。
你應該問的問題是“是 - 原子”嗎? 多數民眾贊成在這里。 當flag達到0時你想做點什么。
你不關心這種情況:
1. Main thread reads flag, and it is 1.
2. Worker changes flag with --
3. Main thread doesn't see that flag is actually 0.
因為在1 ns內,主線程循環並再次嘗試。
你關心的是 - 不是原子的,同時改變它的兩個線程會跳過減量:
1. Thread A reads flag, flag is 2
2. Thread B reads flag, flag is 2
3. Thread A decrements its copy of flag, 2, and writes to flag, flag is 1
4. Thread B decrements its copy of flag, also 2, and writes to flag, flag is 1.
你失去了一個減量。 你想使用__sync_fetch_and_sub (&flag,1),它將原子地遞減標志。
最后,圍繞睡眠旋轉並不是最好的方法。 你想要等待一個條件,等待一個信號 。 當工作線程意識到它們已經將標志遞減到0時,讓工作線程提高條件或信號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.