我正在C++中使用boost開發線程安全的惰性對象模式。然而,在這樣做的時候,如果我的應用程序有多個線程,我會在LazyObject
的calculate()
方法中進入死鎖狀態。C++ Boost線程。如何使用遞歸嘗試鎖定?併發代碼中發生死鎖
這與某種程度上與boost::recursive_mutex::scoped_try_lock
有關,因爲一旦我屏蔽了常規互斥鎖的代碼,並讓其他線程在此互斥鎖上等待,一切都很順利。然而,阻止其他線程的缺點是,它們實際上都需要耗費時間performCalculations()
,因爲一個線程經常將calculated_
標誌更改爲false
。另請注意,performCalculations()
純粹是虛擬的,派生實例將遞歸地調用LazyObject::calculate()
。我想用互斥鎖來屏蔽這個無限遞歸。
你能看到我在哪裏出錯嗎?
我LazyObject
具有以下屬性:
// protects resource frozen_ from simultaneous freeze, unfreeze calls
mutable boost::mutex frozenMutex_;
// protects resource calculated_ from simultaneous update, calculate calls
mutable boost::mutex calculatedMutex_;
// protects that only one thread can simultaneously call calculate
mutable boost::recursive_try_mutex waitMutex_;
// protects that only once can performCalculations be called (from same thread)
mutable boost::mutex blockingMutex_;
// mutex and semaphore for sleeping threads until calculate is ready
mutable boost::mutex condMutex_;
mutable boost::condition_variable condVariable_;
inline void LazyObject::calculate() const {
boost::recursive_mutex::scoped_try_lock lock(waitMutex_);
if (lock) {
//recursive lock lets same thread pass, puts others on wait
if (!calculated_ && !frozen_ && blockingMutex_.try_lock()) {
// blockingMutex ensures that only once same thread
// can call performCalculations
try {
performCalculations();
calculated_ = true;
blockingMutex_.unlock();
condVariable_.notify_all();
} catch (...) {
calculated_ = false;
blockingMutex_.unlock();
condVariable_.notify_all();
throw;
}
}
} else {
// start a non blocking wait until calculation is ready
boost::mutex::scoped_lock lock(condMutex_);
condVariable_.wait(lock);
}
}
其實有一個問題。我沒有考慮到這一點。顯而易見的情況是,一旦計算出懶惰的對象,並隨後調用計算,所有調用都應該返回,因爲對象的狀態是最新的。在上面的實現中,一些線程進入睡眠狀態 – Lauri