2012-11-20 265 views
10

我不知道是否有可能在同一時間鎖定多個互斥鎖,如:鎖定多個互斥鎖

Mutex1.Lock(); 
{ 
    Mutex2.Lock(); 
    { 
      // Code locked by mutex 1 and 2. 
    } 
    Mutex2.Unlock(); 

    // Code locked by mutex 1. 
} 
Mutex1.Unlock(); 

這將是某些情況下非常有用的。謝謝。

+2

是的,這是可能的。只要小心,沒有適當的努力就會很容易導致僵局。 –

回答

12

這是可能的,但鎖定的順序必須在整個應用程序中保持一致,否則會導致死鎖(如果兩個線程以相反的順序獲取鎖,那麼每個線程都可能正在等待另一個鎖釋放一個鎖) 。

推薦使用範圍的鎖,(用std::mutexstd::lock_guard例如)解鎖設備的異常安全,確保鎖總是發佈:

std::mutex mtx1; 
std::mutex mtx2; 

std::lock_guard<std::mutex> mtx1_lock(mtx1); 
{ 
    std::lock_guard<std::mutex> mtx2_lock(mtx2); 
    { 
    } 
} 

如果你的編譯器不支持這些C++ 11層的功能提升在boost::mutexboost::lock_guard中有相似之處。

+0

我使用pthreads,是否有可能保護我的程序免受死鎖而不使用c + + 11?我正在使用pthread_mutex_lock並在.Lock()和.Unlock()函數內解鎖。 – grimgrom

+0

@grimgrom,是的。提到'lock_guard'是因爲它使異常安全性更容易實現,但並不需要避免死鎖。爲了避免死鎖,無論鎖定採集之後的代碼如何退出,都要始終以相同順序獲取鎖並釋放_always_。 – hmjd

+0

@grimgrom,注意你可以很容易地爲你的'Mutex'類編寫你自己的'Lock_guard'類。只需在構造函數中使用'Lock()'和在析構函數中使用'Unlock()'。只要確保'Lock_guard'存儲對'Mutex'實例的引用並且不復制它。 – hmjd

26

std::lock似乎是爲此目的而存在的。

使用死鎖避免算法鎖定給定的可鎖定對象lock1,lock2,...,lockn以避免死鎖。 對象被未鎖定的一系列調用鎖定,try_lock,unlock。如果鎖定或解鎖的調用導致異常,則在重新拋出之前爲任何鎖定的對象調用解鎖。

http://en.cppreference.com/w/cpp/thread/lock

2

C++ 17還提供scoped_lock用於鎖定多個互斥的特定目的,其防止死鎖在RAII風格,類似於lock_guard

#include<mutex> 

std::mutex mtx1, mtx2; 
void foo() 
{ 
    std::scoped_lock lck{mtx1, mtx2}; 
    // proceed 
}