鎖定
鎖定不良:
std::mutex mtx;
void bad_lock_example() {
mtx.lock();
try
{
foo();
bar();
if (baz()) {
mtx.unlock(); // Have to unlock on each exit point.
return;
}
quux();
mtx.unlock(); // Normal unlock happens here.
}
catch(...) {
mtx.unlock(); // Must also force unlock in the presence of
throw; // exceptions and allow the exception to continue.
}
}
這是實現互斥鎖定和解鎖的錯誤方法。為確保使用 unlock()
正確釋放互斥鎖,需要程式設計師確保導致函式退出的所有流程都會導致呼叫 unlock()
。如上所示,這是一個脆弱的過程,因為它需要任何維護者手動繼續遵循模式。
使用適當製作的類來實現 RAII,問題是微不足道的:
std::mutex mtx;
void good_lock_example() {
std::lock_guard<std::mutex> lk(mtx); // constructor locks.
// destructor unlocks. destructor call
// guaranteed by language.
foo();
bar();
if (baz()) {
return;
}
quux();
}
lock_guard
是一個非常簡單的類别範本,只需在其建構函式中呼叫其引數的 lock()
,保持對引數的引用,並在其解構函式中對引數呼叫 unlock()
。也就是說,當 lock_guard
超出範圍時,保證 mutex
被解鎖。如果它超出範圍的原因是例外或提前退貨並不重要 - 所有案件都得到處理; 無論控制流程如何,我們都保證能夠正確解鎖。