boost shared_mutex的例子(多读/一写)?

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

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

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

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

 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信息或多或less是正确的,但是我想纠正一些问题。

 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,即使它没有升级(当我遇到它时我觉得很尴尬)。 所以,如果你所有的读者都是有条件的作家,你需要find另一个解决scheme。

您可以使用boost来创build一个读写locking:

 #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; Lock myLock; void ReadFunction() { ReadLock r_lock(myLock); //Do reader stuff } void WriteFunction() { WriteLock w_lock(myLock); //Do writer stuff } 

为了增加更多的实证信息,我一直在研究可升级锁的整个问题,以及boost shared_mutex(多读/一写)的例子? 是一个很好的答案,即使没有升级,也只有一个线程可以拥有upgrade_lock,这是非常重要的,因为这意味着您不能从共享锁升级到唯一锁,而不必先释放共享锁。 (这已经在别处讨论过,但最有趣的线程在这里http://thread.gmane.org/gmane.comp.lib.boost.devel/214394

然而,我确实发现一个等待升级到锁的线程(即需要等待所有读者释放共享锁)和一个等待相同事件的写入程序锁(即unique_lock)之间的重要(未logging的)区别。

  1. 正在等待shared_mutex上的unique_lock的线程阻塞了所有新的读者进来,他们不得不等待编写者的请求。 这可以确保读者不会饿死作家(但是我相信作家可能会使读者挨饿)。

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

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

使用计数等于读取器数量的信号量。 让每个读者读一个信号量来读取,这样他们都可以同时读取。 然后让作者在写之前把所有的信号计数。 这导致作者等待所有读取完成,然后在写入时阻止读取。

吉姆·莫里斯的大力反应,我偶然发现了这一点,花了我一段时间的计算。 下面是一些简单的代码,显示在提交unique_lock boost(版本1.54)的“请求”后,将阻止所有的shared_lock请求。 这是非常有趣的,因为在我看来,在unique_lock和upgradeable_lock之间进行select允许我们要写优先级或不优先。

另外(1)在吉姆·莫里斯的post中似乎与此相矛盾: 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(); }