lock_guard
unique_lock
boost::mutex mutex; boost::unique_lock<boost::mutex> lock(mutex);
std::unique_lock 與std::lock_guard都能實現自動加鎖與解鎖功能,但是std::unique_lock要比std::lock_guard更靈活,但是更靈活的代價是占用空間相對更大一點且相對更慢一點。
通過實現一個線程安全的隊列來說明兩者之間的差別。
template <typename T> class ThreadSafeQueue{ public: void Insert(T value); void Popup(T &value); bool Empety(); private: mutable std::mutex mut_; std::queue<T> que_; std::condition_variable cond_; };
template <typename T> void ThreadSafeQueue::Insert(T value){ std::lock_guard<std::mutex> lk(mut_); que_.push_back(value); cond_.notify_one(); } template <typename T> void ThreadSafeQueue::Popup(T &value){ std::unique_lock<std::mutex> lk(mut_);
//lambda表達式,是一種匿名函數。方括號內表示捕獲變量。
//當lambda表達式返回true時(即queue不為空),wait函數會鎖定mutex。
//當lambda表達式返回false時,wait函數會解鎖mutex同時會將當前線程置於阻塞或等待狀態。 cond_.wait(lk, [this]{return !que_.empety();}); value = que_.front(); que_.pop(); } template <typename T> bool ThreadSafeQueue::Empty() const{ std::lock_guard<std::mutex> lk(mut_); return que_.empty(); }
上面代碼只實現了關鍵的幾個函數,並使用了C++11新引入的condition_variable條件變量。從Popup與Inert兩個函數看std::unique_lock相對std::lock_guard更靈活的地方在於在等待中的線程如果在等待期間需要解鎖mutex,並在之后重新將其鎖定。而std::lock_guard卻不具備這樣的功能。
- 如果只是為了保證數據同步,那么lock_guard完全夠用;
- 如果除了同步,還需要使用condition進行阻塞時,那么就需要用unique_lock。
- std::unique_lock相對std::lock_guard更靈活的地方在於在等待中的線程如果在等待期間需要解鎖mutex,並在之后重新將其鎖定。而std::lock_guard卻不具備這樣的功能。
- boost還要一個boost::mutex::scoped_lock,這個是boost::unique_lock<boost::mutex>的typedef,在C++11中已經禁用。
