如果我有以下代码:
#include <boost/date_time.hpp>
#include <boost/thread.hpp>
boost::shared_mutex g_sharedMutex;
void reader()
{
boost::shared_lock<boost::shared_mutex> lock(g_sharedMutex);
boost::this_thread::sleep(boost::posix_time::seconds(10));
}
void makeReaders()
{
while (1)
{
boost::thread ar(reader);
boost::this_thread::sleep(boost::posix_time::seconds(3));
}
}
boost::thread mr(makeReaders);
boost::this_thread::sleep(boost::posix_time::seconds(5));
boost::unique_lock<boost::shared_mutex> lock(g_sharedMutex);
...
唯一的锁永远不会被获取,因为总是会有读取器。我想要一个unique_lock,当它开始等待时,阻止任何新的读锁访问互斥锁(根据我的wiki搜索,称为写偏向锁或写首选锁)。有没有一种简单的方法可以用boost做到这一点?或者我需要写我自己的?
发布于 2012-10-11 09:14:40
请注意,我不会评论win32实现,因为它涉及的内容更多,我没有时间详细介绍它。也就是说,它的接口与pthread实现相同,这意味着下面的答案应该是同样有效的。
从v1.51.0开始,boost::shared_mutex的pthread实现的相关部分:
void lock_shared()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
shared_cond.wait(lk);
}
++state.shared_count;
}
void lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
}
state.exclusive=true;
}
while循环条件是与您最相关的部分。对于lock_shared函数(读锁),请注意,只要有一个线程试图获取(state.exclusive_waiting_blocked
)或已经拥有(state.exclusive
)锁,while循环就不会终止。这本质上意味着写锁比读锁具有优先级。
对于锁函数(写锁),只要当前至少有一个线程拥有读锁(state.shared_count
)或另一个线程拥有写锁(state.exclusive
),while循环就不会终止。这基本上为您提供了通常的互斥保证。
至于死锁,只要保证写锁一旦被获取就会被解锁,读锁就会一直返回。至于写锁,只要读锁和写锁在获取后总是保证解锁,它就一定会返回。
如果您想知道,可以使用state_change
互斥锁来确保没有对这两个函数的并发调用。我不会详细介绍解锁函数,因为它们比较复杂。你可以自己查看它们,毕竟你有源代码(boost/thread/pthread/shared_mutex.hpp
) :)
总而言之,这几乎是一个教科书实现,它们已经在广泛的场景中进行了广泛的测试(libs/thread/test/test_shared_mutex.cpp
和整个行业的大规模使用)。我不会太担心,只要你习惯地使用它们(没有递归锁定,总是使用RAII帮助程序进行锁定)。如果您仍然不信任该实现,那么您可以编写一个随机测试,模拟您所担心的任何测试用例,并让它在数百个线程上通宵运行。这通常是梳理死锁的好方法。
现在,为什么您会看到在请求写锁之后获取了一个读锁?在看不到您正在使用的诊断代码的情况下,很难说。读锁很可能是在打印语句(或您正在使用的任何东西)完成之后、在写线程中获得state_change锁之前获得的。
https://stackoverflow.com/questions/12810127
复制相似问题