优化读/写锁的实现

optimize the implementation of read/write locks

本文关键字:实现 写锁 优化      更新时间:2023-10-16

我当前正在使用boost库实现读/写锁,而无需使用sharone_lock和unique_lock。我已经阅读了一些相关问题(例如,在C 11中如何实现读者/作者锁?),但是我仍然想优化实现。

这是我的代码:

enum LockType { NO_LOCK, READ_LOCK, WRITE_LOCK, INC_LOCK };
boost::mutex mutex_;
boost::condition condition_;
LockType lock_;
size_t owner_count_;
void AcquireReadLock() {
    mutex_.lock();
    while (lock_ != NO_LOCK && lock_ != READ_LOCK){
        condition_.wait(mutex_);
    }
    // if there is no lock, then acquire read lock.
    if (lock_ == NO_LOCK) {
        lock_ = READ_LOCK;
        ++owner_count_;
        mutex_.unlock();
        return;
    }
    else {
        // if there is read lock, then still acquire read lock.
        assert(lock_ == READ_LOCK);
        ++owner_count_;
        mutex_.unlock();
        return;
    }
}
void AcquireWriteLock() {
    mutex_.lock();
    while (lock_ != NO_LOCK){
        condition_.wait(mutex_);
    }
    // if there is no lock, then acquire write lock.
    assert(lock_ == NO_LOCK);
    lock_ = WRITE_LOCK;
    mutex_.unlock();
    return;
}
void ReleaseReadLock() {
    mutex_.lock();
    --owner_count_;
    if (owner_count_ == 0) {
        lock_ = NO_LOCK;
    }
    mutex_.unlock();
    // is it correct to use notify_all?
    condition_.notify_all();
}
void ReleaseWriteLock() {
    mutex_.lock();
    lock_ = NO_LOCK;
    mutex_.unlock();
    // is it correct to use notify_all?
    condition_.notify_all();
}

问题是:

  1. 在释放锁时我是否应该使用Notify_all?根据该文档,一旦通知线程,它将重新锁定锁。如果使用notify_all,则多个线程可以重新出现相同的锁定。那会发生什么?并且线程在检查条件之前是否会获取锁(即锁_!= no_lock&& lock _!= read_lock)?

  2. 如何优化程序?显然,在发布读取锁定时,我们只需要通知尝试获取写锁的线程,因为读取从未阻止读取。那么如何实现这个想法?

事先感谢您的帮助!

  1. 发布锁时我是否应该使用Notify_all?根据该文档,一旦通知线程,它将重新锁定锁。如果使用notify_all,则多个线程可以重新出现相同的锁定。那会发生什么?并且线程在检查条件之前是否会获取锁(即锁_!= no_lock&& lock _!= read_lock)?

是的,在释放锁时,应使用Notify_all。所有条件_等待mutex_将一一唤醒,因为他们必须首先锁定sutex_(这是内部完成的条件_等待操作)。

  1. 如何优化程序?显然,在发布读取锁定时,我们只需要通知尝试获取写锁的线程,因为读取从未阻止读取。那么如何实施这个想法?

必须通知所有等待Mutex_的线程,因为某些写作线程可能会等待释放读取锁。

我希望这对您有帮助!

如果使用notify_all,则多个线程可以重新出现相同的锁。

否。每个通知线程都将竞争进行锁定获取,就像mutex_.lock()一样。即使使用 notify_all ,最多可以在当时执行关键部分的代码。因此,使用notify_all是完全正确的。

  1. 如何优化程序?显然,在发布读取锁定时,我们只需要通知尝试获取写锁的线程,因为读取从未阻止读取。那么如何实施这个想法?

作为读取,永不封锁读取,没有读取线程可以 wait()其他读取线程。因此,即使您当前的代码ReleaseReadLock()也只能通知写线程。

因此,在ReleaseReadLock()中,您可以安全地使用notify()而不是notify_all:没有理由唤醒所有写入线程,因为只有其中一个才能aqcuire aqcuire a l/w lock。

至于其他优化,您应该更好地修复手工艺品,在此答案中列出:https://stackoverflow.com/a/12657243/34440745