【问题标题】:What does shared mode mean in shared access?共享模式在共享访问中是什么意思?
【发布时间】:2021-06-28 17:57:54
【问题描述】:

在多线程中,有一个叫做shared_mutex 的东西。当有shared_mutex 时,有两种访问方式。共享访问和独占访问。我已经知道什么是独占访问,但什么是共享访问?据此:https://stackoverflow.com/a/46050121/15976718,“共享访问允许多个线程获取互斥锁,但它们都只能在共享模式下。”他所说的共享模式是什么意思?共享模式有什么作用?在共享模式下,你可以做与独占访问相同的事情吗?

【问题讨论】:

标签: c++ mutex


【解决方案1】:

您可以将它们视为读取器和写入器锁。

假设您使用共享互斥锁保护一个整数。

只要没有线程正在写入,您就可以安全地让两个线程读取它。但是,如果任何线程正在编写它,则不应有其他人在阅读它,也不应由其他人编写它,否则您将面临竞争条件的风险。

所以规则是

  1. 任何数量的线程都可以在共享模式下持有互斥锁。
  2. 如果任何线程以独占模式持有互斥锁,则根本没有其他线程可以以任何模式持有互斥锁。

有一些细节,但这应该让你直觉地理解如何使用它,并把细节挂起来。

当使用 C++ std 容器时,您可以使用共享互斥锁来保护它,并对 const 操作使用共享锁,对非const 操作使用独占锁,并避免基于 C++ 内存模型竞争的竞争条件。 (它仍然不作曲,但还不错)。举个例子。

template<class T>
struct shared_mutex_guarded {
  template<class F>
  auto read(F&& f)const {
    auto l = lock();
    return f(t);
  }
  template<class F>
  auto write(F&& f) {
    auto l = lock();
    return f(t);
  }
  shared_mutex_guarded(T tin):
    t(std::forward<T>(tin))
  {}
private:
  mutable std::shared_mutex m;
  T t;
  auto lock() const {
    return std::shared_lock(m);
  }
  auto lock() {
    return std::unique_lock(m);
  }
};

测试代码:

auto start = std::chrono::steady_clock::now();

shared_mutex_guarded vec = std::vector<int>{1,2,3};
std::jthread a0([&]{
    using namespace std::chrono;
    while(duration_cast<seconds>(steady_clock::now()-start).count() < 3) {
        std::this_thread::sleep_for( 100ms );
        std::stringstream ss;
        vec.read([&](auto& vec){
            std::cerr << "Working...\n";
            for (auto i:vec){
                std::this_thread::sleep_for( 10ms );
                ss << i << ",";
            }
            ss << "\n";
            std::cerr << "Solved!\n";
        });
        std::cerr << ss.str();
    }
});
std::jthread a1([&]{
    using namespace std::chrono;
    while(duration_cast<seconds>(steady_clock::now()-start).count() < 3) {
        std::this_thread::sleep_for( 100ms );
        std::stringstream ss;
        vec.read([&](auto& vec){
            std::cerr << "Summing...\n";
            int sum = 0;
            for (auto i:vec)
            {
                std::this_thread::sleep_for( 10ms );
                sum += i;
            }
            ss << "Sum is " << sum << "\n";
            std::cerr << "Summed!\n";
        });
        std::cerr << ss.str();
    }
});
std::jthread b([&]{
    using namespace std::chrono;
    while(duration_cast<seconds>(steady_clock::now()-start).count() < 3) {
        std::this_thread::sleep_for( 100ms );
        vec.write([&](auto& vec){
            vec.push_back(vec.back()+1);
            for (auto& i:vec)
                i *= 2;
        });
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 2011-06-05
    • 1970-01-01
    • 2020-09-14
    • 2013-07-26
    • 1970-01-01
    相关资源
    最近更新 更多