我有一个多线程应用程序,该应用程序必须经常读取一些数据,并偶尔更新数据。现在,互斥锁可以确保对数据的安全访问,但是这很昂贵,因为我希望多个线程能够同时读取,并且仅在需要更新时才将它们锁定(更新线程可以等待其他线程完成)。 。
我认为这是boost::shared_mutex
应该做的,但是我不清楚如何使用它,也没有找到明确的例子。
有人有我可以用来入门的简单示例吗?
我有一个多线程应用程序,该应用程序必须经常读取一些数据,并偶尔更新数据。现在,互斥锁可以确保对数据的安全访问,但是这很昂贵,因为我希望多个线程能够同时读取,并且仅在需要更新时才将它们锁定(更新线程可以等待其他线程完成)。 。
我认为这是boost::shared_mutex
应该做的,但是我不清楚如何使用它,也没有找到明确的例子。
有人有我可以用来入门的简单示例吗?
Answers:
看来您将执行以下操作:
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
}
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
}
另请注意,与shared_lock不同,即使没有升级,单个线程也只能一次获得一个upgrade_lock(我认为遇到此问题时很尴尬)。因此,如果您所有的读者都是有条件的作家,则需要寻找其他解决方案。
boost::unique_lock< boost::shared_mutex > lock(lock);
读取boost::unique_lock< boost::shared_mutex > lock(
_access );
吗?
从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
}
对于较旧的版本,可以使用具有相同语法的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;
typedef boost::unique_lock< Lock > WriteLock; typedef boost::shared_lock< Lock > ReadLock;
。
只是为了增加一些经验信息,我一直在研究整个可升级锁的问题,还有用于boost shared_mutex(多次读取/一次写入)的示例?添加重要信息,即即使不升级也只有一个线程可以具有upgrade_lock,这是一个很好的答案,这一点很重要,因为这意味着您必须先释放共享锁才能从共享锁升级到唯一锁。(这已经在其他地方进行了讨论,但是最有趣的线程在这里http://thread.gmane.org/gmane.comp.lib.boost.devel/214394)
但是,我确实发现了等待升级到锁的线程(即需要等待所有读取器释放共享锁的线程)和写入器锁在等待同一件事(即unique_lock)之间的重要区别(未记录)。
等待shared_mutex上的unique_lock的线程会阻止任何新的读取器进入,他们必须等待写入器的请求。这样可以确保读者不会饿死作家(但是我相信作家会饿死读者)。
等待upgradeable_lock升级的线程允许其他线程获得共享锁,因此如果读者非常频繁,则可能会饿死该线程。
这是要考虑的重要问题,可能应该记录在案。
使用计数等于读取器数量的信号量。让每个读者对信号量进行一次计数才能阅读,这样他们就可以同时阅读所有内容。然后让编写者在编写之前记录所有信号量。这导致写入器等待所有读取完成,然后在写入时阻止读取。
吉姆·莫里斯(Jim Morris)做出了很大的回应,我偶然发现了这一点,花了我一段时间才弄清楚。以下是一些简单的代码,这些代码显示在提交“ unique_lock boost”(版本1.54)“请求”后,将阻止所有shared_lock请求。这很有趣,因为在我看来,在unique_lock和upgradeable_lock之间进行选择可以允许我们要写入优先级还是不优先。
同样,吉姆·莫里斯(Jim Morris)的帖子中的(1)似乎与此矛盾: 提高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();
}