difference between std::mutex and std::shared_mutex

巧了我就是萌 提交于 2019-12-04 17:37:36

问题


I came across an std::shared_mutex in C++17. what exactly is std::shared_mutex and how it is different from std::mutex?


回答1:


As noted in the documentation

The shared_mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads. In contrast to other mutex types which facilitate exclusive access, a shared_mutex has two levels of access:

  • shared - several threads can share ownership of the same mutex.
  • exclusive - only one thread can own the mutex.

Shared mutexes are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so.

This has a variety of uses, but one common one is to implement a Read Write Lock where you could have multiple threads reading shared data, but only one thread exclusively writing at any time. So when you have multiple readers the mutex acts in "shared mode", but when a write is requested it changes into "exclusive mode".




回答2:


A mutex is either locked or not.

A shared_mutex is either locked exclusively, or locked shared, or not.

Any number of clients can shared lock a shared mutex.

If anyone has it exclusive locked, nobody else can hold any locks.

On windows, this is the SWRLOCK type -- and in fact, this lock is typically used to implement read-write locks; many readers allowed, but writing must be exclusive.

Here is some sample code to create two template wrappers for shared and non-shared mutexes. In one case, we have read and write operations that aquire different locks. In the other, we just have access:

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



回答3:


std::shared_mutex can be useful especially in cases where data structure (like DNS cache) gets rarely updated. Using a std::mutex to protect the data structure could be overly pessimistic, because it eliminates the possible concurrency in reading the data structure when it isn’t undergoing modification. Multiple threads can have a shared lock on the same std::shared_mutex at the same time.

One such example from Anthony Williams book:

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

Here, function find_entry basically does the Read operation, whereas update_or_add_entry performs the Write operation.

So, it can said that std::shared_mutex is a typical reader-writer mutex, because it allows for two different kinds of usage: exclusive access by a single “writer” thread or shared, concurrent access by multiple “reader” threads.



来源:https://stackoverflow.com/questions/46452973/difference-between-stdmutex-and-stdshared-mutex

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!