【问题标题】:Locking multiple mutexes锁定多个互斥锁
【发布时间】:2012-11-20 23:07:02
【问题描述】:

我想知道是否可以同时锁定多个互斥锁,例如:

 Mutex1.Lock();
 {
     Mutex2.Lock();
     {
          // Code locked by mutex 1 and 2.
     }
     Mutex2.Unlock();

     // Code locked by mutex 1.
 }
 Mutex1.Unlock();

这在某些情况下会非常有用。谢谢。

【问题讨论】:

  • 是的,有可能。请注意,如果没有适当的勤奋,这样做很容易导致死锁。

标签: c++ multithreading mutex


【解决方案1】:

std::lock 似乎就是为此目的而存在的。

使用死锁避免算法锁定给定的可锁定对象 lock1、lock2、...、lockn 以避免死锁。 对象被一系列未指定的 lock、try_lock、unlock 调用锁定。如果调用 lock 或 unlock 导致异常,则在重新抛出之前为任何锁定的对象调用 unlock。

http://en.cppreference.com/w/cpp/thread/lock

【讨论】:

    【解决方案2】:

    C++17 还提供了scoped_lock,用于锁定多个互斥锁以防止 RAII 样式中的死锁,类似于lock_guard

    #include<mutex>
    
    std::mutex mtx1, mtx2;
    void foo()
    {
        std::scoped_lock lck{mtx1, mtx2};
        // proceed
    }
    

    【讨论】:

    • 不幸的是,当前在 ubuntu 中默认的 gcc v5.4 尚不支持 std::scoped_lock。不过可以使用升压模拟。
    【解决方案3】:

    这是可能的,但锁定的顺序必须在整个应用程序中保持一致,否则可能会导致死锁(如果两个线程以相反的顺序获取锁,则每个线程可能会等待另一个线程释放其中一个锁)。

    建议使用范围锁定和解锁工具来确保异常安全,以确保始终释放锁定(例如std::lock_guardstd::mutex):

    std::mutex mtx1;
    std::mutex mtx2;
    
    std::lock_guard<std::mutex> mtx1_lock(mtx1);
    {
        std::lock_guard<std::mutex> mtx2_lock(mtx2);
        {
        }
    }
    

    如果您的编译器不支持这些 C++11 功能,boost 在boost::mutexboost::lock_guard 中具有类似的功能。

    【讨论】:

    • 我正在使用 pthreads,是否可以在不使用 c++11 的情况下保护我的程序免受死锁?我在 .Lock() 和 .Unlock() 函数中使用 pthread_mutex_lock 和解锁。
    • @grimgrom,是的。提到了lock_guard,因为它使异常安全更容易实现,但不需要避免死锁。为避免死锁,请确保始终以相同的顺序获取锁并始终释放,无论锁获取之后的代码如何退出。
    • @grimgrom,请注意,您可以轻松地为您的 Mutex 类编写自己的 Lock_guard 类。只需 Lock() 在构造函数中和 Unlock() 在析构函数中。请确保Lock_guard 存储了对Mutex 实例的引用并且不复制它。
    • 如果其他地方的代码在mtx1 之前锁定mtx2,同时此代码锁定mtx1 然后mtx2,那么锁守卫不会拯救你,它会死锁。两个线程都将永远等待另一个人释放他们需要的那个。这就是这个答案开头提到的内容,但似乎已被 RAII 讨论所掩盖。死锁是多锁的主要问题。
    • 这个例子是不安全的,正如 doug65536 已经提到的,除非你能保证每次这些互斥锁被锁定,它们总是以相同的顺序被锁定(祝你好运)。按照 Pubby 的建议,绝对安全的方法是使用 std::lock。
    猜你喜欢
    • 2021-02-19
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2010-09-16
    • 2012-12-25
    • 2013-02-11
    相关资源
    最近更新 更多