我正在使用 boost 在 C++ 中开发一个线程安全的惰性对象模式。但是,在这样做时,如果我的应用程序有多个线程,我会在 LazyObject
的 calculate()
方法中进入死锁状态。
这在某种程度上与 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);
}
}
最佳答案
您提供的一个功能看起来不错。
但是,我强烈怀疑您有锁排序问题。您在一个类中有 5 个互斥体。您需要保证这些互斥量始终以相同顺序锁定。否则你会遇到死锁。
看起来你有一个非常复杂的锁定顺序:
- 5 个不同的互斥体
- 1是递归的
- 至少尝试锁定
关于C++ Boost 线程。如何使用递归尝试锁?死锁发生在并发代码中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8087490/