繁体   English   中英

std :: mutex和std :: shared_mutex之间的区别

[英]difference between std::mutex and std::shared_mutex

我在C++17遇到了一个std::shared_mutex 什么是std::shared_mutex以及它与std::mutex区别?

文档所述

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

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

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

这有多种用途,但一个常见的用途是实现一个Read Write Lock ,你可以让多个线程读取共享数据,但只有一个线程可以随时独占写入。 因此,当您有多个读卡器时,互斥锁将以“共享模式”运行,但是当请求写入时,它将变为“独占模式”。

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); }
};

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

安东尼威廉姆斯的一个例子:

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基本上执行Read操作,而update_or_add_entry执行Write操作。

因此,可以说std::shared_mutex是典型的读写器互斥体 ,因为它允许两种不同的用法:单个“编写器”线程的独占访问或多个“读取器”线程的共享,并发访问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM