鎖定

鎖定不良:

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 被解鎖。如果它超出範圍的原因是例外或提前退貨並不重要 - 所有案件都得到處理; 無論控制流程如何,我們都保證能夠正確解鎖。