您将如何在 C 11 中实现自己的读/写锁?

新手上路,请多包涵

我有一组需要用读/写锁保护的数据结构。我知道 boost::shared_lock,但我想有一个使用 std::mutex、std::condition_variable 和/或 std::atomic 的自定义实现,以便我可以更好地理解它是如何工作的(稍后再调整它) .

每个数据结构(可移动,但不可复制)都将继承自一个名为 Commons 的类,该类封装了锁定。我希望公共界面看起来像这样:

 class Commons {
public:
    void read_lock();
    bool try_read_lock();
    void read_unlock();

    void write_lock();
    bool try_write_lock();
    void write_unlock();
};

…这样它就可以被某些人公开继承:

 class DataStructure : public Commons {};

我正在编写科学代码,通常可以避免数据竞争;这个锁主要是为了防止我以后可能会犯的错误。因此,我的优先级是低读取开销,因此我不会过多地妨碍正确运行的程序。每个线程可能会在自己的 CPU 内核上运行。

你能告诉我(伪代码可以)一个读者/作者锁吗?我现在拥有的应该是防止作家饥饿的变体。到目前为止,我的主要问题是 read_lock 在检查读取是否安全与实际增加读取器计数之间存在差距,之后 write_lock 知道要等待。

 void Commons::write_lock() {
    write_mutex.lock();
    reading_mode.store(false);
    while(readers.load() > 0) {}
}

void Commons::try_read_lock() {
    if(reading_mode.load()) {
        //if another thread calls write_lock here, bad things can happen
        ++readers;
        return true;
    } else return false;
}

我对多线程有点陌生,我真的很想了解它。在此先感谢您的帮助!

原文由 jack 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 920
1 个回答

我相信这就是您正在寻找的:

 class Commons {
    std::mutex write_m_;
    std::atomic<unsigned int> readers_;

public:
    Commons() : readers_(0) {
    }

    void read_lock() {
        write_m_.lock();
        ++readers_;
        write_m_.unlock();
    }

    bool try_read_lock() {
        if (write_m_.try_lock()) {
            ++readers_;
            write_m_.unlock();
            return true;
        }
        return false;
    }

    // Note: unlock without holding a lock is Undefined Behavior!
    void read_unlock() {
        --readers_;
    }

    // Note: This implementation uses a busy wait to make other functions more efficient.
    //       Consider using try_write_lock instead! and note that the number of readers can be accessed using readers()
    void write_lock() {
        while (readers_) {}
        if (!write_m_.try_lock())
            write_lock();
    }

    bool try_write_lock() {
        if (!readers_)
            return write_m_.try_lock();
        return false;
    }

    // Note: unlock without holding a lock is Undefined Behavior!
    void write_unlock() {
        write_m_.unlock();
    }

    int readers() {
        return readers_;
    }
};

对于 C++17 以来的记录,我们有 std::shared_mutex,请参阅: https ://en.cppreference.com/w/cpp/thread/shared_mutex

原文由 dwto 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题