我很少想到在兩個連續的表達式之間,函數調用和它的主體的第一個表達式的執行之間,或者在構造函數的調用和它的執行之間發生了什麼初始化。然後,我開始閱讀關於併發...std :: mutex鎖定的順序
1)在連續兩次調用std::thread
的構造用相同的可調用(如函數,仿函數,拉姆達),其身體開始有std::lock_guard
初始化與同std::mutex
對象,標準是否保證第一個thread
構造函數調用對應的線程首先執行受鎖定保護的代碼?如果標準沒有作出保證,那麼是否存在任何理論上或實踐上的可能性,對應於第二個構造函數調用的線程首先執行受保護的代碼? (第一thread
構造函數調用的初始化或身體的執行期間例如重系統負載)
這裏的一個全局std::mutex
m
對象和全局unsigned
num
初始化爲1
。功能foo
的開啓支架{
和std::lock_guard
之間只有空白。在main
中,有兩個std::thread
和t1
和t2
。 t1
首先調用線程構造函數。 t2
第二次調用線程構造函數。每個線程都使用指向foo
的指針構造。 t1
調用foo
與unsigned
參數1
。 t2
調用foo
與unsigned
參數2
。取決於哪個線程先鎖定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
構造函數的可調用函數」?
4.)標準任務「首先調用傳遞給thread
構造函數的可調用函數」是否始終暗示「首先鎖定mutex
」;前提是在可調用函數體內,不存在代碼,該代碼依賴於初始化行之前傳遞給可調用函數的參數嗎? (也排除任何可調用的本地static
變量,像所謂的次數的計數器,可用於故意拖延某些呼叫。)
不,是的,不清楚,沒有。 –