boost shared_mutex的示例(多次读取/一次写入)?

kev*_*n42 113 c++ multithreading boost mutex boost-thread

我有一个多线程应用程序,必须经常读取一些数据,偶尔会更新数据.现在,互斥锁可以保持对数据安全的访问,但是它很昂贵,因为我希望多个线程能够同时读取,并且只在需要更新时将其锁定(更新线程可以等待其他线程完成) .

我认为这是boost::shared_mutex应该做的,但我不清楚如何使用它,并没有找到一个明确的例子.

有没有人有一个我可以用来开始的简单例子?

mmo*_*cny 164

1800信息或多或少是正确的,但我想纠正一些问题.

boost::shared_mutex _access;
void reader()
{
  boost::shared_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access
}

void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }

  // do more work here, without anyone having exclusive access
}

void unconditional_writer()
{
  boost::unique_lock< boost::shared_mutex > lock(_access);
  // do work here, with exclusive access
}
Run Code Online (Sandbox Code Playgroud)

另请注意,与shared_lock不同,只有一个线程可以同时获取upgrade_lock,即使它没有升级(当我遇到它时,我认为这很尴尬).所以,如果你的所有读者都是有条件的作家,你需要找到另一种解决方案.

  • 不应行`的boost :: unique_lock <提高:: shared_mutex>锁(锁);``读升压:: unique_lock <提高:: shared_mutex>锁(`**_**访问`);`? (8认同)
  • 这是一个众所周知的助推问题.它似乎在boost 1.50 beta处得到解决:https://svn.boost.org/trac/boost/ticket/5516 (6认同)
  • 最后一个警告很奇怪.如果一次只有一个线程可以容纳upgrade_lock,那么upgrade_lock和unique_lock之间有什么区别? (4认同)
  • @Ken我不是很清楚,但是如果当前获得了一些shared_locks,那么upgrade_lock的好处是它不会阻塞(至少在你升级到unique之前).但是,尝试获取upgrade_lock的第二个线程将阻止,即使第一个没有升级到unique,这是我没想到的. (2认同)

180*_*ION 99

看起来你会做这样的事情:

boost::shared_mutex _access;
void reader()
{
  // get shared access
  boost::shared_lock<boost::shared_mutex> lock(_access);

  // now we have shared access
}

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);
  // now we have exclusive access
}
Run Code Online (Sandbox Code Playgroud)

  • 这是我第一次使用boost,我是一个C++新手,所以也许有一些我缺少的东西 - 但在我自己的代码中,我必须指定类型,如下所示:boost :: shared_lock <shared_mutex> lock (_访问); (7认同)
  • 我添加了缺少的模板参数. (4认同)
  • 我试图自己使用它,但我收到了一个错误.'lock'之前缺少模板参数.有任何想法吗? (2认同)
  • @shaz这些是作用域的,但如果需要,你可以使用.unlock()尽早发布它们. (2认同)

Yoc*_*mer 45

您可以使用boost来创建读写锁:

#include <shared_mutex>

typedef std::shared_mutex Lock;
typedef std::unique_lock< Lock > WriteLock;
typedef std::shared_lock< Lock > ReadLock;

Lock myLock;


void ReadFunction()
{
    ReadLock r_lock(myLock);
    //Do reader stuff
}

void WriteFunction()
{
     WriteLock w_lock(myLock);
     //Do writer stuff
}
Run Code Online (Sandbox Code Playgroud)

  • 我还会说`typedef boost :: unique_lock <Lock> WriteLock; typedef boost :: shared_lock <Lock> ReadLock;`. (5认同)
  • 不需要包含整个thread.hpp.如果您只需要锁,请包含锁.这不是内部实施.将包含保持在最低限度. (5认同)
  • 绝对是最简单的实现,但我认为将互斥锁和锁定引用为锁定令人困惑.互斥锁是互斥锁,锁可以将其保持在锁定状态. (4认同)

Jim*_*ris 17

只是为了增加一些经验信息,我一直在调查可升级锁的整个问题,以及boost shared_mutex的示例(多次读取/一次写入)?添加重要信息是一个很好的答案,即只有一个线程可以拥有upgrade_lock,即使它没有升级,这很重要,因为这意味着您无法在不释放共享锁的情况下从共享锁升级到唯一锁.(这已在别处讨论,但最有趣的主题是http://thread.gmane.org/gmane.comp.lib.boost.devel/214394)

但是我确实发现等待升级到锁的线程(即需要等待所有读取器释放共享锁)和等待同一事物的写入器锁(即unique_lock)之间存在重要(无证)差异.

  1. 正在等待shared_mutex上的unique_lock的线程阻止任何新的读者进入,他们必须等待写入者请求.这可以确保读者不会让作家们挨饿(但我相信作家会让读者们挨饿).

  2. 等待upgradeable_lock升级的线程允许其他线程获得共享锁,因此如果读者非常频繁,则该线程可能会被饿死.

这是一个需要考虑的重要问题,可能应该记录在案.

  • `Terekhov算法'确保在`1.`中,作者不能使读者饿死.见[this](http://stackoverflow.com/questions/12082405/boost-shared-lock-read-preferred/13445989#13445989).但是`2.`是真的.upgrade_lock不保证公平.请参阅[this](http://stackoverflow.com/questions/21773618/starvation-with-upgrade-lock?noredirect=1#comment32949054_21773618). (3认同)