在C++中读写锁实现

use*_*858 5 c++ concurrency multithreading mutex locking

我试图使用shared_mutex在C++中使用读/写锁

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock >  WriteLock;
typedef boost::shared_lock< Lock >  ReadLock;

class Test {
    Lock lock;
    WriteLock writeLock;
    ReadLock readLock;

    Test() : writeLock(lock), readLock(lock) {}

    readFn1() {
        readLock.lock();
        /*
             Some Code
        */
        readLock.unlock();
    }

    readFn2() {
        readLock.lock();
        /*
             Some Code
        */
        readLock.unlock();
    }

    writeFn1() {
        writeLock.lock();
        /*
             Some Code
        */
        writeLock.unlock();
    }

    writeFn2() {
        writeLock.lock();
        /*
             Some Code
        */
        writeLock.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

代码似乎工作正常,但我有一些概念性的问题.

Q1.我已经看到了在http://en.cppreference.com/w/cpp/thread/shared_mutex/lock上使用unique_lock和shared_lock的建议,但我不明白为什么因为shared_mutex已经支持lock和lock_shared方法了?

Q2.这段代码是否有可能导致写入饥饿?如果是,那么我怎样才能避免饥饿呢?

Q3.有没有其他锁定类我可以尝试实现读写锁?

Chr*_*phe 3

Q1:互斥锁包装器的使用

建议使用包装器对象而不是直接管理互斥体,以避免代码被中断且互斥体未释放、使其永远锁定的不幸情况。

这就是RAII的原理。

但这仅当您的 ReadLock 或 WriteLock 位于使用它的函数的本地时才有效。

例子:

readFn1() {
    boost::unique_lock< Lock > rl(lock);  
    /*
         Some Code 
         ==> imagine exception is thrown
    */
    rl.unlock();   // this is never reached if exception thrown 
}  // fortunately local object are destroyed automatically in case 
   // an excpetion makes you leave the function prematurely      
Run Code Online (Sandbox Code Playgroud)

在您的代码中,如果其中一个函数被中断,这将不起作用,因为您的 ReadLock WriteLock 对象是 Test 的成员,而不是设置锁定的函数的本地成员。

Q2:写饥饿

目前尚不完全清楚如何调用读者和作者,但确实存在风险:

  • 只要读取器处于活动状态,写入器就会被 unique_lock 阻塞,等待互斥锁以独占模式获取。
  • 然而,只要wrtier在等待,新的读者就可以获得对共享锁的访问,从而导致unique_lock进一步延迟。

如果你想避免饥饿,你必须确保等待的写入者确实有机会设置他们的 unique_lock。例如,在读者中添加一些代码来检查作者在设置锁定之前是否正在等待。

Q3 其他锁定类

不太确定您在寻找什么,但我觉得condition_variable您可能会感兴趣。但逻辑有点不同。

也许,您还可以通过跳出框框思考来找到解决方案:也许有一种合适的无锁数据结构可以通过稍微改变方法来促进读者和作者的共存?