是否有一个提升设施允许写偏置锁定?

时间:2012-10-10 00:04:56

标签: c++ multithreading boost

如果我有以下代码:

#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有一个简单的方法吗?或者我需要自己编写吗?

1 个答案:

答案 0 :(得分:2)

请注意,我不会对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)或另一个线程拥有写锁定({{1),while循环就不会终止}})。这基本上为您提供了通常的互斥保障。

对于死锁,只要获得写锁定保证解锁,读锁就会一直返回。至于写锁定,只要读取锁定和写入锁定始终保证解锁,就可以保证返回。

如果您想知道,state.exclusive互斥锁用于确保不会同时调用这些函数中的任何一个。我不打算通过解锁功能,因为他们有更多的参与。你可以随意查看它们,毕竟你有源(state_change):)

总而言之,这几乎是一本教科书实施,它们已在各种场景中得到广泛测试(boost/thread/pthread/shared_mutex.hpp并在整个行业中得到广泛使用)。我不会太担心,只要你习惯性地使用它们(没有递归锁定并且总是使用RAII助手锁定)。如果您仍然不相信实现,那么您可以编写一个随机测试,模拟您担心的任何测试用例,让它在数百个线程上运行一夜。这通常是解决僵局的好方法。

现在为什么在请求写锁定后会看到获取读锁?很难说没有看到你正在使用的诊断代码。有可能是在完成print语句(或任何你正在使用的语句)之后以及在写入线程中获取state_change锁之前获取读锁定。