我在C++17遇到了一个std::shared_mutex。std::shared_mutex到底是什么?它与std::mutex有何不同
发布于 2017-09-28 00:35:43
正如the documentation中所指出的那样
shared_mutex类是一个同步原语,可用于保护共享数据不被多个线程同时访问。与促进独占访问的其他互斥类型不同,shared_mutex有两个级别的访问:
共享互斥通常用于多个读取器可以同时访问同一资源而不会导致数据竞争的情况,但只有一个写入器可以这样做。
这有多种用途,但一个常见的用途是实现一个Read Write Lock,其中可以有多个线程读取共享数据,但任何时候只有一个线程以独占方式写入数据。因此,当你有多个读取器时,互斥以“共享模式”工作,但当请求一个写操作时,它就变成了“独占模式”。
发布于 2017-09-28 02:10:13
mutex已锁定或未锁定。
shared_mutex要么以独占方式锁定,要么以共享方式锁定,或者不是。
任意数量的客户端可以共享锁定一个共享互斥锁。
如果任何人独占地锁定了它,其他人就不能持有任何锁。
在windows上,这是SWRLOCK类型--实际上,这个锁通常用于实现读写锁;许多读取器允许,但写必须是独占的。
下面是为共享和非共享互斥锁创建两个模板包装器的示例代码。在一种情况下,我们有获得不同锁的读写操作。在另一种情况下,我们只能访问:
template<class T, class M=std::mutex>
struct mutex_guarded {
template<class F>
auto access( F&& f ) {
auto l = lock();
return std::forward<F>(f)(t);
}
template<class F>
auto access( F&& f ) const {
auto l = lock();
return std::forward<F>(f)(t);
}
mutex_guarded(mutex_guarded const&)=delete;
mutex_guarded& operator=(mutex_guarded const&)=delete;
template<class...Ts>
mutex_guarded( Ts&&...ts ):t(std::forward<Ts>(ts)...){}
mutex_guarded()=default;
protected:
mutable M m;
T t;
auto lock() { return std::unique_lock<M>(m); }
};
template<class T, class M=std::shared_mutex>
struct shared_mutex_guarded:private mutex_guarded<T, M> {
using base = mutex_guarded<T, M>;
template<class F>
auto read( F&& f ) const { return access(std::forward<F>(f)); }
template<class F>
auto write( F&& f ) { return access(std::forward<F>(f)); }
using base::base;
protected:
using base::access;
template<class F>
auto access( F&& f ) const {
auto l = lock();
return std::forward<F>(f)(this->t);
}
using base::lock;
auto lock() const { return std::shared_lock<M>(this->m); }
};发布于 2017-09-28 00:52:48
std::shared_mutex很有用,特别是在数据结构(如DNS缓存)获取而很少更新的情况下。使用std::mutex来保护数据结构可能过于悲观,因为它消除了在数据结构未被修改时读取数据结构时可能出现的并发。多个线程可以同时在同一个std::shared_mutex上拥有一个共享锁。
安东尼·威廉姆斯( Anthony Williams )一书中的一个例子:
class dns_cache
{
std::map<std::string,dns_entry> entries;
mutable boost::shared_mutex entry_mutex;
public:
dns_entry find_entry(std::string const& domain) const
{
boost::shared_lock<boost::shared_mutex> lk(entry_mutex);
std::map<std::string,dns_entry>::const_iterator const it = entries.find(domain);
return (it==entries.end()) ? dns_entry() : it->second;
}
void update_or_add_entry(std::string const& domain,
dns_entry const& dns_details)
{
std::lock_guard<boost::shared_mutex> lk(entry_mutex);
entries[domain] = dns_details;
}
};这里,函数find_entry基本上执行读操作,而update_or_add_entry执行写操作。
因此,可以说std::shared_mutex是一个典型的读取器-写入器互斥锁,因为它允许两种不同的用法:由单个“写入器”线程独占访问或由多个“读取器”线程共享并发访问。
https://stackoverflow.com/questions/46452973
复制相似问题