2013-07-07 108 views

回答

11

是的,那個特別的代碼片段是線程安全的;不需要屏障或鎖。

這是事件的時間表相對於你的代碼:

thread 1 
-------- 
    | 
    int x = 0; 
    (write 0 to x) 
    | 
    std::thread    thread 2 
    (start thread 2) --------> -------- 
    |       | 
    join();      x = 1; 
    (thread 1 suspended)   (write 1 to x) 
    .       | 
    .       thread 2 returns 
    .       | 
    (thread 1 resumes) <------- x 
    | 
    std::cout << x; 
    (read from x) 
    | 
    thread 1 returns 
    | 
    x 

正如你所看到的,在任何一點x由多於一個線程訪問。實際上,正如你猜測的那樣,使用join()有效地使所有對x的訪問按順序發生join()提供了同步來代替從鎖獲得的同步。

基本上,你擁有的是一個如何使用零併發多線程的例子。

當然,這僅僅是因爲調用join(),這是在您提供的代碼片段中創建線程後立即發生的。如果不是有這樣的事情:

int x = 0; 
std::thread t([&]{ x = 1; }); 
std::cout << x; 
t.join(); // Move join() call here 

的時間表,而不是看起來可能是這樣:

thread 1 
-------- 
    | 
    int x = 0; 
    (write 0 to x) 
    | 
    std::thread    thread 2 
    (start thread 2) --------> -------- 
    |       | 
    std::cout << x;    x = 1; 
    (read from x)    (write 1 to x) <-- PROBLEM! 
    |       | 
    join();      | 
    (thread 1 suspended)   | 
    .       | 
    .       thread 2 returns 
    .       | 
    (thread 1 resumes) <------- x 
    | 
    thread 1 returns 
    | 
    x 

改變的join()這樣的順序將引入的比賽。

+2

這是一個非常全面的說'是'的方式。 –

+1

我想我將從現在開始使用該圖表樣式來發佈線程。 – Prime

+0

除非join()有一些特殊的保證,那麼即使在join()和打印舊結果之後,主線程也可以使用x的緩存值,否? – mitchnull