2017-08-28 69 views
1

這裏的例子只是想保護iData以確保只有一個線程同時訪問它。一個互斥對比多個互斥。哪一個更適合線程池?

struct myData; 
myData iData; 

方法1,調用函數中的互斥體(可以創建多個互斥鎖):

void _proceedTest(myData &data) 
    { 
     std::mutex mtx; 
     std::unique_lock<std::mutex> lk(mtx); 
     modifyData(data); 
     lk.unlock; 
    } 

    int const nMaxThreads = std::thread::hardware_concurrency(); 
    vector<std::thread> threads; 
    for (int iThread = 0; iThread < nMaxThreads; ++iThread) 
    { 
     threads.push_back(std::thread(_proceedTest, iData)); 
    } 

    for (auto& th : threads) th.join(); 

方法二,只用一個互斥體:

void _proceedTest(myData &data, std::mutex &mtx) 
    { 
     std::unique_lock<std::mutex> lk(mtx); 
     modifyData(data); 
     lk.unlock; 
    } 
    std::mutex mtx; 
    int const nMaxThreads = std::thread::hardware_concurrency(); 
    vector<std::thread> threads; 
    for (int iThread = 0; iThread < nMaxThreads; ++iThread) 
    { 
     threads.push_back(std::thread(_proceedTest, iData, mtx)); 
    } 

    for (auto& th : threads) th.join(); 
  1. 我要打確保方法1(多重互斥鎖)確保只有一個線程可以同時訪問iData。
  2. 如果方法1是正確的,不確定方法1比方法2更好嗎? 謝謝!
+0

您的意思是方法1並不保證iData僅被一個線程訪問? – lightrek

+0

它應該如何在不同線程之間共享'std :: mutex'? – user0042

回答

3
  1. 我想確保的方法1(多個互斥鎖),確保只有一個線程可以在同一時間訪問IDATA。

你的第一個例子在堆棧上創建一個本地互斥變量,它不會與其他線程共享。因此它完全沒用。
它不保證獨家訪問iData

  • 如果方法1是正確的,不能確定方法1是方法2的更好?
  • 這是不正確的。

    +0

    剛剛注意到方法2也不正確。應使用std :: ref來包裝iData和mtx – lightrek

    +1

    @lightrek您可能需要['std :: ref()'](http://en.cppreference.com/w/cpp/utility/functional/ref)讓它正常工作。 – user0042

    0

    當您離開_proceedTest範圍時,版本1中的互斥鎖將超出範圍,因此鎖定互斥鎖是沒有意義的,因爲它不會被其他線程訪問。

    在第二個版本中,多個線程可以共享互斥鎖(只要它不超出範圍,例如作爲類成員),這樣一個線程可以鎖定它,另一個線程可以看到它被鎖定(並且將不能鎖定它,因此術語互斥)。

    2

    方法1僅適用於互斥變量爲static的情況。

    void _proceedTest(myData &data) 
    { 
        static std::mutex mtx; 
        std::unique_lock<std::mutex> lk(mtx); 
        modifyData(data); 
        lk.unlock; 
    } 
    

    這將使mtx通過輸入_proceedTest所有線程共享。

    由於static函數範圍變量只對該函數的用戶可見,所以對於傳入的data而言,它並不是一個足夠的鎖。這是因爲可以想象,多個線程可能會調用每個想要操作的不同函數data。因此,儘管方法1是可挽救的,但即使鎖與數據之間的內聚力較弱,方法2仍然更好。

    2

    其他答案在技術層面上是正確的,但有一個重要的語言無關的東西缺失:你總是更喜歡減少不同互斥/鎖的數量/ ...!

    因爲:只要你有一個以上一個件事,一個線程需要獲取爲了做一些事情(來然後釋放所有獲取的鎖)爲了變得至關重要。

    當你有2把鎖,你必須在不同的代碼塊,如:

    getLockA() { 
        getLockB() { 
        do something 
        release B 
    release A 
    

    而且

    getLockB() { 
        getLockA() { 
    

    就可以快速運行到死鎖 - 因爲兩個線程/進程每個人可以獲得一個鎖 - 然後他們都被卡住了,等待另一個釋放鎖。當然 - 當看到上面的例子時,「你永遠不會犯錯,並且總是先選A然後B」。但是如果這些鎖存在於應用程序的完全不同的部分呢?而且它們不是以相同的方法或類來獲得的,而是在說3,5個嵌套方法調用過程中獲得的?

    因此:當你可以解決你的問題與一個鎖 - 使用一個只鎖!你需要做的事情越多,死鎖的風險就越高。