共享的静音和静音之间的差异(为什么两者都存在于C 17中)

Difference between shared mutex and mutex (why do both exist in C++ 17)?

本文关键字:存在 两者都 之间 共享 为什么      更新时间:2023-10-16

没有在线示例生动地证明这一点。在http://en.cppreference.com/w/cpp/header/shared_mutex上看到了一个示例仍然不清楚。有人可以帮忙吗?

通过使用普通静音,您可以保证对某种关键资源的独家访问,而别无其他。共享的静音通过允许两个级别的访问来扩展此功能:共享和独家,如下:

  • 独家访问可以防止其他任何其他线程获得静音,就像普通的静音一样。其他线程是否试图获取共享或独家访问都没关系。
  • 共享访问允许多个线程获取sutex,但仅在共享模式下它们的全部。直到所有先前的共享持有人都返回了Mutex之前,才获得独家访问(通常,只要独家请求等待,新共享的请求就会排队以在之后授予独家访问权限)。/li>

一个典型的方案是一个数据库:同时读取一个线程的几个线程是否无关紧要。但是,对数据库的修改至关重要 - 如果某些线程读取数据而另一个线程正在编写数据,则可能会收到不一致的数据。因此,所有阅读都必须在允许写作之前完成,并且必须等待新阅读才能完成。写作后,可能会再次同时发生。

编辑: sidenote:

为什么读者需要锁?

这是为了防止作者在阅读时获取锁。此外,它可以防止新的读者获得锁定尚未持有的锁。

共享的互联克具有两个级别的访问'共享'和"独家"。多个线程可以获取共享访问,但只有一个可以保留"独家"访问(其中包括没有共享访问)。

常见的情况是读/写锁。回想一下,只有当两个线程访问相同的数据至少一个是写入

时,才能发生数据竞赛

这是数据的优点可能是许多读者可以读取的,但是当作者需要访问时,他们必须获得对数据的独家访问。

为什么两者都有?一方面,独家锁构成了普通的静音,因此可以说只有共享。但是,可以使用较少的特色类型来避免共享锁定实现中的开销。

这是一个示例(从此处的示例稍微改编http://en.cppreference.com/w/cpp/thread/shared_mutex)。

#include <iostream>
#include <mutex>  
#include <shared_mutex>
#include <thread>
  
std::mutex cout_mutex;//Not really part of the example...
void log(const std::string& msg){
    std::lock_guard guard(cout_mutex);
    std::cout << msg << std::endl;
}
 
class ThreadSafeCounter {
 public:
  ThreadSafeCounter() = default;
 
  // Multiple threads/readers can read the counter's value at the same time.
  unsigned int get() const {
    std::shared_lock lock(mutex_);//NB: std::shared_lock will shared_lock() the mutex.
    log("get()-begin");
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    auto result=value_;
    log("get()-end");
    return result;
  }
 
  // Only one thread/writer can increment/write the counter's value.
  void increment() {
    std::unique_lock lock(mutex_);
    value_++;
  }
 
  // Only one thread/writer can reset/write the counter's value.
  void reset() {
    std::unique_lock lock(mutex_);
    value_ = 0;
  }
 
 private:
  mutable std::shared_mutex mutex_;
  unsigned int value_ = 0;
};
 
int main() {
  ThreadSafeCounter counter;
 
  auto increment_and_print = [&counter]() {
    for (int i = 0; i < 3; i++) {
      counter.increment();
      auto ctr=counter.get();
      {
          std::lock_guard guard(cout_mutex);
          std::cout << std::this_thread::get_id() << ' ' << ctr << 'n';
      }
    }
  };
 
  std::thread thread1(increment_and_print);
  std::thread thread2(increment_and_print);
  std::thread thread3(increment_and_print);
 
  thread1.join();
  thread2.join();
  thread3.join();
}

可能的部分输出:

get()-begin
get()-begin
get()-end
140361363867392 2
get()-end
140361372260096 2
get()-begin
get()-end
140361355474688 3
//Etc...

请注意,两个get()-begin()返回如何显示两个线程在读取过程中持有共享锁。

"共享的sutexes通常在多个读者可以同时访问相同资源而不会引起数据竞赛的情况下使用,但只有一个作者可以这样做。"

>

cppreference.com

当您需要阅读/作者锁时,这很有用:https://en.wikipedia.org/wiki/wiki/readers–Writer_lock

相关文章: