请注意,我不会评论 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
):)
All in all, this is pretty much a text book implementation and they've been extensively tested in a wide range of scenarios (libs/thread/test/test_shared_mutex.cpp
and massive use across the industry). I wouldn't worry too much as long you use them idiomatically (no recursive locking and always lock using the RAII helpers). If you still don't trust the implementation, then you could write a randomized test that simulates whatever test case you're worried about and let it run overnight on hundreds of thread. That's usually a good way to tease out deadlocks.
Now why would you see that a read lock is acquired after a write lock is requested? Difficult to say without seeing the diagnostic code that you're using. Chances are that the read lock is acquired after your print statement (or whatever you're using) is completed and before state_change lock is acquired in the write thread.