【问题标题】:Upgrading read lock to write lock without releasing the first in C++11?升级读锁到写锁而不释放C++ 11中的第一个锁?
【发布时间】:2016-01-25 13:35:42
【问题描述】:

我知道在 C++14 中使用 boost::UpgradeLockable 是可能的。
C++11 有没有类似的东西?

【问题讨论】:

  • @RichardHodges 我看不出该链接有何相关性。该界面中的哪个位置允许升级锁?
  • @Yakk 嗯,你是对的。那么这就引出了一个问题,标准提案是否缺少某些内容,或者可升级的锁根本没有必要?
  • @RichardHodges 如果在客户端代码中可以像在std 中一样高效地完成它,那么此时我们是否应该将它放在std 中?也许吧。
  • 我不明白你的问题。如果要使用 Boost.Threads,那么为什么需要 C++14? Boost.Threads 多年来一直拥有可升级的shared_mutex,并且只需要 C++98。

标签: c++ c++11 readwritelock


【解决方案1】:

可以在更简单的锁定原语之上编写可升级的锁。

struct upgradeable_timed_mutex {
  void lock() {
    upgradable_lock();
    upgrade_lock();
  }
  void unlock() {
    upgrade_unlock();
    upgradable_unlock();
  }
  void shared_lock() { shared.shared_lock(); }
  void shared_unlock() { shared.shared_unlock(); }

  void upgradable_lock() { unshared.lock(); }
  void ungradable_unlock() { unshared.unlock(); }

  void upgrade_lock() { shared.lock(); }
  void upgrade_unlock() { shared.unlock(); }
private:
  friend struct upgradable_lock;
  std::shared_timed_mutex shared;
  std::timed_mutex unshared;
};

和类似的定时和尝试变体。请注意,连续访问两个互斥锁的定时变体必须做一些额外的工作以避免花费高达请求时间的 2 倍,try_lock 必须小心第一个锁的状态,以防第二个锁失败。

然后你必须写upgradable_lock,并能够根据请求生成std::unique_lock

这自然是手写的线程安全代码,所以不太可能是正确的。

在 C++1z 中,您也可以编写不定时版本(使用 std::shared_mutexstd::mutex)。


不太具体,一次只能有一个可升级或写入锁。这就是unshared 互斥锁所代表的内容。

只要您持有unshared,就没有其他人正在写入受保护的数据,因此您可以在完全不持有共享互斥锁的情况下读取它。

当你想升级时,你可以在共​​享互斥锁上获取一个唯一的锁。只要没有读者尝试升级到可升级,这不会死锁。这将读者排除在阅读之外,您可以写入,然后您释放它并返回到只读状态(您只持有非共享互斥体)。

【讨论】:

  • 升级时,此解决方案是否需要在寻求名为shared 的互斥锁的唯一锁之前删除shared_lock?在这种情况下,第二个互斥锁 unshared 将是多余的,还是我遗漏了什么?
  • @RichardHodges 可升级锁根本不拥有共享锁。它只是在非共享互斥锁上拥有一个 unique_lock。然后它在升级时直接在共享互斥锁上获得一个 unique_lock。重点是升级时不会丢失读锁。
猜你喜欢
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2011-11-25
相关资源
最近更新 更多