将 shared_lock 升级为独特的锁使用、时序和设计

use*_*947 3 c++ multithreading boost boost-thread c++11

我正在更新以前使用自己的读写锁定机制的代码(此代码是在 C++11 之前编写的,并且 std::shared_mutex 尚不存在)以使用 C++ 的 std 版本。

有 ReadLock 和 WriteLock 两个类,可以通过调用方法将 ReadLock 升级为 WriteLock。WriteLock 也可以随时获取,无需从 shared_lock 升级。阅读 shared_lock 的 C++ std 版本,我认为它很简单。

ReadLock 将被 shared_lock 替换 WriteLock 将被 unique_lock 替换并且可以随时触发调用 lock() 来获取 Writelock 升级到 Writelock 将只分两步执行解锁 shared_lock 和锁定 unique_lock

我现在的问题是,当我阅读讨论时,可能会出现特定问题,并且像这样的线程引起了关注(来自 Howard Hinnant 的线程) std::shared_timed_mutex 上的共享锁可以升级为排他锁吗?

所以我考虑使用 boost 版本,因为它支持 upgrade_lock 和 boost::upgrade_to_unique_lock,但我对如何处理它的设计感到困惑。

WriteLock 类可以同时表示 unique_lock 和/或 upgrade_lock 和 upgrade_to_unique_lock 对象,因为正如我上面提到的,WriteLock 也可以在没有 shared_lock 的情况下实现。

另外,如果我使用 boost 中的 upgrade_lock,我对如何显式触发 lock() 和 unlock() 机制感到困惑;boost::upgrade_lock 有一个构造函数,它接受 defer_lock 作为参数,并具有我可以随时使用的 lock() 和 unlock() 方法,但是如果我们使用 boost::upgrade_to_unique_lock() 将其升级为唯一锁,我看不到相同的功能,创建 upgrade_to_unique_lock() 的对象会自动转换并锁定它。

这是我试图实现方法 1 基本操作的伪代码

    void foo()
    {
        ReadLock readLock = someWrapper->AcquireReader();    // return a shared lock
        ...
        WriteLock writeLock = readLock->UpgradeToWriter();   // returns a unique lock
        writeLock->Lock();
        // do something here
    }   // writelock are unlock since constructor is called
Run Code Online (Sandbox Code Playgroud)

方法 2 直接写锁

    void foo()
    {
        WriteLock writeLock = someWrapper->GetWriter();   // acquire lock straight
        writeLock->Lock();
        // do something here
    }   // writelock are unlock since constructor is called
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是

  1. 我担心如果我使用 std C++ 有效,我需要使用 boost 还是 C++ std::shared_mutex 就足够了?在上面的示例中,UpgradeToWriter() 和 GetWriter() 都将返回一个带有 unique_lock 的对象,但 Upgrade 只会先解锁 shared_lock。
  2. 如果我使用 boost 版本,我应该如何处理设计,因为 upgrade_to_unique_lock 是与 unique_lock 不同的类型?我在想 WriteLock 类都包含 unique_lock、upgrade_lock 和 boost:upgrade_to_unique_lock 的定义,并且无论是升级还是简单的获取都会被锁定,这让我想到最后一个也是最后一个问题
  3. 如何为 boost:upgrade_to_unique_lock 显式或延迟/触发锁定?因为它没有 defer_lock 参数,也没有 lock() 和 unlock() 方法,只有构造函数来做他的事情?

从使用 boost::upgrade_to_unique_lock 的 boost 示例来看,所有示例都类似于下面的代码,创建一个对象自动触发转换和锁定。

void writer()
{
  // get upgradable access
  boost::upgrade_lock<boost::shared_mutex> lock(_access);

  // get exclusive access
  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock); // <-- want this to be performed or triggered explicitly, how?
  // now we have exclusive access
}
Run Code Online (Sandbox Code Playgroud)

先谢谢了,我知道这里有 C++ 专家可以帮助兄弟

Dav*_*rtz 5

这是你缺少的:

  1. 两个线程各有一个可升级的读锁。
  2. 两个线程都尝试将它们的读锁升级为写锁。
  3. 在所有其他读锁被释放之前,两个线程都不能向前推进。
  4. 两个线程都持有一个读锁。

这是一个僵局。所以你有两个选择:

  1. 确保这种情况永远不会发生:一次只有一个线程可以持有一个可升级的读锁。
  2. 打破死锁:当您尝试升级读锁时,结果可能是操作失败并要求线程在尝试获取写锁之前释放读锁。