首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::mutex与std::shared_mutex的区别

std::mutex与std::shared_mutex的区别
EN

Stack Overflow用户
提问于 2017-09-28 00:32:56
回答 3查看 11.2K关注 0票数 19

我在C++17遇到了一个std::shared_mutexstd::shared_mutex到底是什么?它与std::mutex有何不同

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-28 00:35:43

正如the documentation中所指出的那样

shared_mutex类是一个同步原语,可用于保护共享数据不被多个线程同时访问。与促进独占访问的其他互斥类型不同,shared_mutex有两个级别的访问:

  • shared -多个线程可以共享同一互斥锁的所有权。
  • exclusive -只有一个线程可以拥有互斥锁。

共享互斥通常用于多个读取器可以同时访问同一资源而不会导致数据竞争的情况,但只有一个写入器可以这样做。

这有多种用途,但一个常见的用途是实现一个Read Write Lock,其中可以有多个线程读取共享数据,但任何时候只有一个线程以独占方式写入数据。因此,当你有多个读取器时,互斥以“共享模式”工作,但当请求一个写操作时,它就变成了“独占模式”。

票数 17
EN

Stack Overflow用户

发布于 2017-09-28 02:10:13

mutex已锁定或未锁定。

shared_mutex要么以独占方式锁定,要么以共享方式锁定,或者不是。

任意数量的客户端可以共享锁定一个共享互斥锁。

如果任何人独占地锁定了它,其他人就不能持有任何锁。

在windows上,这是SWRLOCK类型--实际上,这个锁通常用于实现读写锁;许多读取器允许,但写必须是独占的。

下面是为共享和非共享互斥锁创建两个模板包装器的示例代码。在一种情况下,我们有获得不同锁的读写操作。在另一种情况下,我们只能访问:

代码语言:javascript
复制
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); }
};
票数 8
EN

Stack Overflow用户

发布于 2017-09-28 00:52:48

std::shared_mutex很有用,特别是在数据结构(如DNS缓存)获取而很少更新的情况下。使用std::mutex来保护数据结构可能过于悲观,因为它消除了在数据结构未被修改时读取数据结构时可能出现的并发。多个线程可以同时在同一个std::shared_mutex上拥有一个共享锁。

安东尼·威廉姆斯( Anthony Williams )一书中的一个例子:

代码语言:javascript
复制
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是一个典型的读取器-写入器互斥锁,因为它允许两种不同的用法:由单个“写入器”线程独占访问或由多个“读取器”线程共享并发访问。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46452973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档