2016-01-24 17 views
0

我最近開始學習POSIX線程,並且我知道當你有兩個線程Main和B時,如果在線程B的創建中引用變量作爲void指針,線程B可以連續地在線程Main中更改一個變量。在運行時更改線程的void指針會發生什麼?

這使我想知道如何讓線程在線程B中不斷更改變量。我編寫了一個程序來測試是否更改發送的參數通過運行線程B更改線程B,然後更改引用的變量。它沒有做任何事情。這個結果是正確的嗎?

所以基本上:

void *someFunc(void *var) { 
    int *num=(int*) var; 
    int num2=*num; 
    while (true) { 
     if (num2==1) { 
      *num=3; 
     } else { 
      *num=5; 
     } 
    } 
    return NULL;  
} 

someVar=1; 
pthread_t threadB; 
if(pthread_create(&threadB, NULL, someFunc , &someVar)) { 
    return 1; 
} 
someVar=2; 
//then join both threads later and print someVar 
//will someVar be 3 or 5? 

基本上,當我參考使用線程創建的空指針的變量,將未來該變量的變化會影響新創建的線程?如果不是這樣,爲了不斷改變它,是否有一些特別要求呢?我應該看看鎖/互斥鎖還是僅將someFunc放入類中並更改其初始化變量? 謝謝!

+1

它被稱爲[Race Condition](http://stackoverflow.com/questions/34510/what-is-a-race-condition),它觸發[undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior)(即不可能說出會發生什麼)。另請注意,自從C++ 11 [在C++中有多線程的標準工具](http://en.cppreference.com/w/cpp/thread),並且不再需要pthread。 – Drop

+1

爲了更好地理解[順序一致](https://en.wikipedia.org/wiki/Sequential_consistency)C++ 11的Data Race Free Memory模型,請參閱着名的Herb Sutter的講話:[C++ and Beyond 2012:Herb Sutter - 原子<>武器](https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2) – Drop

+0

我意識到我應該看看這類東西的全局變量。謝謝! – msun

回答

-3

因爲您通過someFunc指針傳遞someVar,然後將其複製到指針num,所以對someVar的任何更改都會立即更改* num的值。

但是num2不會受到對someVar的更改的影響,因爲num2是分配給線程B堆棧的不同變量。因此,while循環的結果將由分配給num2的值決定,線程開始。這可以是1或2,具體取決於主線程和線程B運行的速度。這種依賴是一種稱爲「競爭條件」的非確定性行爲,您需要非常小心以避免它。

+1

建議使用非同步變量來替代「低級構造」,如「鎖和互斥體」,這簡直是無稽之談。當一個線程中的寫入操作在另一個線程中變得可見時,您無法保證!請參閱@Drop在評論中提供的鏈接。 –

+0

也許我應該在這裏添加一些缺失的解釋:我使用許多不同的機制親自在C++中完成了大量的多線程。與多線程相關的主要問題是正確性(線程安全性,沒有死鎖,沒有競爭條件)和性能。我的方法是隻在真正需要的地方使用鎖定。有技術可以在不鎖定的情況下進行安全的多線程(請參閱https://en.wikipedia.org/wiki/Multiversion_concurrency_control)。特別是,如果你想要的只是表示一個動作的完成,一個簡單的共享指針是最簡單和安全的。 –

+0

因此,你在某處存儲了該動作的結果,然後設置了標誌(我認爲這是你的意思是共享指針,而不是'std :: shared_ptr')它完成了嗎?寫重新排序會打破這一點,所以我不同意這是安全的。使用原子可以使這個工作甚至沒有鎖定,是真的,但它也不是沒有同步。 –

1

int num2=*num; 

創建拷貝數的由主線程指向。你有一場比賽,因此:如果在複製之前改變了,有一件事會發生;否則,子線程將永遠不會看到更改。

相關問題