C++两个锁比一个更好吗?

3

我有一份资源(向量、列表等),我想让多个写者/读者都能够访问。

我不确定怎样做才能实现最佳性能,即在数据结构被锁定时读取器需要使用最小数量的锁。是否最好使用两个锁,一个称为readmutex,另一个称为writemutex?

例如:

struct Foo {
    mutex writemutex_;
    mutex readmutex_;
    vector<string> data_;
    void write(string data)
    {
        lock_guard<mutex> locker(writemutex_);
        data_.emplace_back(move(data));
    }
    string get(int index) const {
        // I don't need to lock for read, but what if the data is being written?
        // and so should I lock lockmutex_? If so, then readmutex_ is unnecessary?
        // is there some cleaver way that I can avoid readers from being blocked?
        return data_[index];
    }

};

这里还可以使用哪些其他的同步技术?

1
通常可以通过使用“读/写锁”或“共享锁”来解决这个问题;它可以被锁定以进行读取(如果没有为写入锁定,则多个线程可以执行该操作)或写入(只有一个线程可以执行该操作,而且仅在未被完全锁定时才能执行)。C++14将引入std::shared_lock来解决这个问题。在那之前,您可以使用具有此功能的线程库(例如Boost)。 - Angew is no longer proud of SO
如何使用条件锁定?在写入时进行锁定。当同时发生写入时,仅在读取时进行锁定。 - freakish
1
@freakish:你不会知道的。写操作可能发生在检查到写操作正在进行之后,但实际读取开始之前的任何时间。 - MSalters
3个回答

2
您需要读写锁。但是您应该考虑到,在某些情况下,读写锁可能比独占锁更慢。
有很多实现方法,例如在boost中。WinAPI也有一个(自Vista或Server 2008以来)。

1

您可以使用shared_mutex,该工具可在boost中使用,并将成为C++14的一部分。

struct Foo 
{
    using mutex = boost::shared_mutex;
    using write_lock = boost::unique_lock<mutex>;
    using read_lock = boost::shared_lock<mutex>;

    mutable mutex mutex_;
    vector<string> data_;

    void write(string data)
    {
        write_lock lock{ mutex_ };
        data_.emplace_back(move(data));
    }

    string get(int index) const 
    {
        read_lock lock{ mutex_ };
        return data_[index];
    }
};

0
回答您的主要问题:不,使用两个锁并不更好。事实上,这是不正确的。您需要写锁来防止竞争,在持有写锁期间不需要任何额外的读锁。
其他答案确实有正确的替代方案(shared_mutex,它实现了读写锁),但没有解释为什么需要它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接