C++ 中 std::lock_guard 與 std::unique_lock 的區別
C++ 11 中新增了二個處理 lock 的 wrapper,分別是 std::lock_guard 以及 std::unique_lock,
我們首先來看 C++ 11 對 std::lock_guard 的實作:
template<class _Mutex> class lock_guard<_Mutex> { // specialization for a single mutex public: typedef _Mutex mutex_type; explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock _MyMutex.lock(); } lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) { // construct but don't lock } ~lock_guard() _NOEXCEPT { // unlock _MyMutex.unlock(); } lock_guard(const lock_guard&) = delete; lock_guard& operator=(const lock_guard&) = delete; private: _Mutex& _MyMutex; };
從程式碼中,可以看到其主要就是在建構子中上鎖,並於解構子中解鎖,因此 lock_guard 是一個非常輕量的 wrapper,只提供於 block 自動上鎖與解鎖 (避免開發者忘記) 接著我們再來看 std::unique_lock,根據 cppreference 的描述:The class unique_lock is a general-purpose mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership, and use with condition variables.我們可以從描述中得知 std::unique_lock 除了自動上鎖與解鎖外,亦提供了一些 wrapper function 讓你在 Timed Lockable 的 mutex 可以呼叫 try_lock_for, try_lock_until 等 function,另外更重要的是 std::unique_lock 提供了與 std::condition_variable 搭配來 wait 特定 event 完成,以下是 std::condition_variable 與 std::unique_lock 用於解決 LeetCode 1114. Print in Order 的一個範例class Foo {
protected:
    int index;
    std::mutex m_mutex;
    std::condition_variable m_cv;
    
    
public:
    Foo() {
        index = 1;
    }
    void first(function<void()> printFirst) {
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            printFirst();
            index = 2;
        }
        m_cv.notify_all();
    }
    void second(function<void()> printSecond) {
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_cv.wait(lock, [this]() { return index == 2;});
            printSecond();
            index = 3;
        }
        m_cv.notify_all();
    }
    void third(function<void()> printThird) {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_cv.wait(lock, [this]() { return index == 3;});
        printThird();
    }
};我們在 second function 內使用 condition_variable 來確保 index 要變成 2 (也就是 first 已先執行),如果 index 不是 2 的話,就會使用 condition_variable 釋放 lock 並讓當前的 thread wait 直到 first function 的 thread 1 來喚醒自己,如果 index 已是 2 的話才會往下執行,並於執行完成後喚醒正在等待的 thread 3 (third) ~以上就是對於 C++ 11 lock_guard 與 unique_lock 的說明 ~ 
留言
張貼留言