[英]Order of std::mutex locking
我很少考慮兩個連續表達式之間發生的事情,在對函數的調用和它的主體的第一個表達式的執行之間,或者在對構造函數的調用和它的初始化程序的執行之間發生的事情。 然后我開始閱讀並發性...
1.)在std::thread
的構造函數中連續兩次調用具有相同的可調用函數(例如function,functor,lambda),其主體以std::lock_guard
初始化與相同的std::mutex
對象開始,是std::lock_guard
保證第一個thread
構造函數調用對應的線程首先執行受鎖保護的代碼?
2.)如果標准沒有做出保證,那么第二個thread
構造函數調用對應的線程是否有理論或實際可能首先執行受保護的代碼? (例如,執行初始化程序或第一個thread
構造函數調用的主體期間的系統負載很重)
這是一個全局std::mutex
對象m
和一個初始化為1
的全局unsigned
num
。 函數foo
的主體開口括號{
和std::lock_guard
之間只有空格。 在main
,有兩個std::thread
s t1
和t2
。 t1
調用線程構造函數。 t2
調用第二個線程構造函數。 每個線程都使用指向foo
的指針構造。 t1
用unsigned
參數1
調用foo
。 t2
用unsigned
參數2
調用foo
。 根據哪個線程首先鎖定mutex
,在兩個線程執行了受鎖保護的代碼之后, num
的值將是4
或3
。 num
將等於4
,如果t1
擊敗t2
的鎖。 否則, num
將等於3
。 我通過循環並在每個循環結束時將num
重置為1
來運行100,000次試驗。 (據我所知,結果不是也不應該依賴於哪個線程首先join()
。)
#include <thread>
#include <mutex>
#include <iostream>
std::mutex m;
unsigned short num = 1;
void foo(unsigned short par) {
std::lock_guard<std::mutex> guard(m);
if (1 == num)
num += par;
else
num *= par;
}
int main() {
unsigned count = 0;
for (unsigned i = 0; i < 100000; ++i) {
std::thread t1(foo, 1);
std::thread t2(foo, 2);
t1.join();
t2.join();
if (4 == num) {
++count;
}
num = 1;
}
std::cout << count << std::endl;
}
最后, count
等於100000
,所以事實證明t1
每次都贏得比賽。 但這些試驗沒有任何證據。
3.)標准命令“首先調用thread
構造函數”是否總是暗示“首先調用傳遞給thread
構造函數的callable”?
4.)標准命令“首先調用傳遞給thread
構造函數的callable”總是暗示“首先鎖定mutex
”; 假設在callable的主體內,沒有代碼依賴於在std::lock_guard
初始化的行之前傳遞給callable的參數? (還排除任何可調用的本地static
變量,如調用次數的計數器,可用於故意延遲某些調用。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.