我能在同一线程中的shared_lock和unique_lock之间共享一个mutex吗?

5

考虑以下函数:

 std::shared_mutex mutex;
 
 void foo() {
     std::shared_lock readLock{ mutex };
     // ...
     // read-only part of the function
     // ...
     {
         std::unique_lock lock{ mutex, std::adopt_lock }
         // ...
         // read/write part
         // ...
     }
     // ... some other read part ...
 }

最初,该函数只有一个std::unique_lock用于其所有部分。它运行良好,但作为优化的一部分,它的某些部分被包装在std::shared_lock中。对我来说,这看起来完全合法,但在尝试后发现,一些死锁开始出现(不一定是在函数中,但显然这个改变是问题的根本原因)

请问是否有人能够详细说明这种方法是否定义良好,以及为什么会导致死锁问题的出现?


1
第一个:这个操作不会锁定互斥量进行写入,只会锁定互斥量进行读取。第二个:unique_lock的析构函数将解锁互斥量,但在此之前该互斥量并未被锁定。 - gerum
2个回答

7

看起来你正在尝试将共享锁升级为独占锁。你做错了 - std::shared_mutex 不支持递归和升级。先释放共享锁,然后正常地独占锁。

std::shared_mutex mutex;

void foo()
{
    {
        std::shared_lock readLock{ mutex };
        // ...
        // read-only part of the function
        // ...
    }
    {
        std::unique_lock writeLock{ mutex };
        // ...
        // read/write part
        // ...
    }
    // ... some other read part ...
}

在提案N3568中有一个std::upgrade_lock,但它没有被纳入标准。

0

您正在使用adopt_lock调用unique_lock,但这不会在构造时锁定互斥量。您可能希望在锁定unique_lock之前释放readLock。
或者,您可以为unique_lock部分添加一个单独的互斥量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接