C++ Boost 线程。如何使用递归尝试锁?死锁发生在并发代码中

标签 c++ boost thread-safety deadlock

我正在使用 boost 在 C++ 中开发一个线程安全的惰性对象模式。但是,在这样做时,如果我的应用程序有多个线程,我会在 LazyObjectcalculate() 方法中进入死锁状态。

这在某种程度上与 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/

相关文章:

c++ - 为什么 std::shuffle 和 std::sort 一样慢(甚至慢)?

C++ - 返回 C++11 std::array

C++ 泛型变量

c++ - Boost,在io_service.post之前创建线程池

c++ - 绑定(bind) 1 次复制构造函数调用

android - 在另一个 Acitivity 获得焦点后返回到 SurfaceView

java - 在Web应用程序中使用不同的线程进行处理

c++ - 如何降低该算法的计算复杂度?

c++ - 从私有(private) vector 公开访问和赋值运算符

c# - 如何使使用队列线程的异步方法安全