我正在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