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 的說明 ~
留言
張貼留言