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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/989795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:16:16  来源:igfitidea点击:

Example for boost shared_mutex (multiple reads/one write)?

c++multithreadingboostmutexboost-thread

提问by kevin42

I have a multithreaded app that has to read some data often, and occasionally that data is updated. Right now a mutex keeps access to that data safe, but it's expensive because I would like multiple threads to be able to read simultaneously, and only lock them out when an update is needed (the updating thread could wait for the other threads to finish).

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

I think this is what boost::shared_mutexis supposed to do, but I'm not clear on how to use it, and haven't found a clear example.

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

Does anyone have a simple example I could use to get started?

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

采纳答案by 1800 INFORMATION

It looks like you would do something like this:

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

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
}

回答by mmocny

1800 INFORMATION is more or less correct, but there are a few issues I wanted to correct.

1800 INFORMATION 或多或少是正确的,但有几个问题我想更正。

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
}

Also Note, unlike a shared_lock, only a single thread can acquire an upgrade_lock at one time, even when it isn't upgraded (which I thought was awkward when I ran into it). So, if all your readers are conditional writers, you need to find another solution.

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

回答by Yochai Timmer

Since C++ 17 (VS2015) you can use the standard for read-write locks:

从 C++ 17 (VS2015) 开始,您可以使用读写锁标准:

#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
}

For older version, you can use boost with the same syntax:

对于旧版本,您可以使用具有相同语法的 boost:

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

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

回答by Jim Morris

Just to add some more empirical info, I have been investigating the whole issue of upgradable locks, and Example for boost shared_mutex (multiple reads/one write)?is a good answer adding the important info that only one thread can have an upgrade_lock even if it is not upgraded, that is important as it means you cannot upgrade from a shared lock to a unique lock without releasing the shared lock first. (This has been discussed elsewhere but the most interesting thread is here http://thread.gmane.org/gmane.comp.lib.boost.devel/214394)

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

However I did find an important (undocumented) difference between a thread waiting for an upgrade to a lock (ie needs to wait for all readers to release the shared lock) and a writer lock waiting for the same thing (ie a unique_lock).

但是,我确实发现了等待升级到锁的线程(即需要等待所有读者释放共享锁)和等待相同事物(即 unique_lock)的写者锁之间的重要(未记录)区别。

  1. The thread that is waiting for a unique_lock on the shared_mutex blocks any new readers coming in, they have to wait for the writers request. This ensures readers do not starve writers (however I believe writers could starve readers).

  2. The thread that is waiting for an upgradeable_lock to upgrade allows other threads to get a shared lock, so this thread could be starved if readers are very frequent.

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

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

This is an important issue to consider, and probably should be documented.

这是一个需要考虑的重要问题,可能应该记录下来。

回答by R Virzi

Use a semaphore with a count that is equal to the number of readers. Let each reader take one count of the semaphore in order to read, that way they can all read at the same time. Then let the writer take ALL the semaphore counts prior to writing. This causes the writer to wait for all reads to finish and then block out reads while writing.

使用计数等于读取器数量的信号量。让每个读者对信号量进行一次计数以便阅读,这样他们就可以同时阅读。然后让作者在写入之前获取所有信号量计数。这会导致写入器等待所有读取完成,然后在写入时阻止读取。

回答by dale1209

Great response by Jim Morris, I stumbled upon this and it took me a while to figure. Here is some simple code that shows that after submitting a "request" for a unique_lock boost (version 1.54) blocks all shared_lock requests. This is very interesting as it seems to me that choosing between unique_lock and upgradeable_lock allows if we want write priority or no priority.

Jim Morris 的反应很好,我偶然发现了这一点,我花了一段时间才想明白。下面是一些简单的代码,它表明在提交对 unique_lock boost(版本 1.54)的“请求”后会阻止所有 shared_lock 请求。这很有趣,因为在我看来,在 unique_lock 和 upgradeable_lock 之间进行选择允许我们想要写优先级还是没有优先级。

Also (1) in Jim Morris's post seems to contradict this: Boost shared_lock. Read preferred?

另外(1)在 Jim Morris 的帖子中似乎与此矛盾: Boost shared_lock。阅读首选?

#include <iostream>
#include <boost/thread.hpp>

using namespace std;

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > UniqueLock;
typedef boost::shared_lock< Lock > SharedLock;

Lock tempLock;

void main2() {
    cout << "10" << endl;
    UniqueLock lock2(tempLock); // (2) queue for a unique lock
    cout << "11" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    lock2.unlock();
}

void main() {
    cout << "1" << endl;
    SharedLock lock1(tempLock); // (1) aquire a shared lock
    cout << "2" << endl;
    boost::thread tempThread(main2);
    cout << "3" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(3));
    cout << "4" << endl;
    SharedLock lock3(tempLock); // (3) try getting antoher shared lock, deadlock here
    cout << "5" << endl;
    lock1.unlock();
    lock3.unlock();
}