[英]std::lock_guard seems to give thread safety despite scoped block
mutex m;
void thread_function()
{
static int i = 0;
for(int j =0; j<1000; j++)
{
{ //this scope should make this ineffective according to my understanding
lock_guard<mutex> lock(m);
}
i++;
cout<<i<<endl;
}
}
我從2個線程調用此函數。 因此,如果函數以線程安全的方式運行,則int i的期望值為1000 * 2 = 2000。
沒有互斥體,結果在1990年到2000年之間變化,正如打印i時所預期的那樣(由於非原子int i)。 插入沒有范圍塊的鎖定防護裝置可以防止這種情況發生。
但是,根據我的理解,在它周圍使用scoped塊應該使它立即獲取並釋放鎖,因此在寫入int i時不再有線程安全性。 但是,我注意到我永遠是2000。 我誤會了什么嗎?
您的理解是正確的,結果總是2000
可能與機器有關。 原因可能是在機器上的i++
語句之前的同步恰好導致線程以足夠的時間距離執行它以避免競爭條件。 但是,如上所述,這不能保證。
正如其他人已經告訴過你的那樣,問題是你的i++
非常接近線程同步,以至於它(實際上總是)在線程被搶占之前設法進行更新。
如果我們改變你的程序:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex m;
void thread_function()
{
static int i = 0;
for (int j = 0; j < 1000; j++)
{
{ //this scope should make this ineffective according to my understanding
std::lock_guard<std::mutex> lock(m);
}
std::cout << "Printing some stuff. Weee!" << std::endl; // <- New line
i++;
std::cout << i << std::endl;
}
}
int main()
{
std::thread t1(thread_function);
std::thread t2(thread_function);
t1.join();
t2.join();
return 0;
}
然后有時候兩個線程將不再總和到2000.你仍然會比沒有鎖定時更少地遇到競爭狀態,但這只是顯示了競爭條件和未定義行為的主要危險:你的程序實際上可以工作最多當時 ,即使按照標准嚴格錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.