【问题标题】:how to avoid non-deterministic read caused by concurrent write如何避免并发写引起的非确定性读
【发布时间】:2015-07-16 21:38:14
【问题描述】:

并发写入导致的非确定性读取可以通过以下代码演示:

class Bar {
  int val_;
  std::mutex m_;
 public:
  explicit Bar(int v) : val_(v) {}

  int val() {
    std::lock_guard<std::mutex> l(m_);
    return val_;
  }

  void set(int v) {
    std::lock_guard<std::mutex> l(m_);
    val_ = v;
  }
};


class Foo {
  Bar* bar_;
 public:
  explicit Foo(Bar* bar) : bar_(bar) {}
  int val() const { return bar_.val(); }
};

Bar bar(1);
Foo foo(&bar);
cout << foo.val() << endl;  // 1
bar.set(2);  // probably executed in another thread
cout << foo.val() << endl;  // 2

我很想知道避免此类问题的设计模式/编码实践是什么。

我能想到的一个解决方案是制作“深拷贝”,即 Foo 将拥有它所依赖的数据的一致快照,因此所有读取都会得到相同的结果。如果 Foo 拥有 Bar,我们可以将 Bar ref 计数,并让 Foo 维护 Bar 的不同版本的列表(所有对 Bar 的突变都通过 Foo),并且客户端只能获得 Foo 的“快照视图”,它只能访问一个Bar 的版本,即一致的视图。但是,如果 Foo 不拥有 Bar,它就会变得一团糟,我在这里想不出一个好的解决方案。

我的观点是,要么数据所有者需要提供版本化访问权限,要么必须有一个策略强制在读取器发布数据之前不应发生写入。

【问题讨论】:

    标签: c++ design-patterns data-structures concurrency mutex


    【解决方案1】:

    如果您不想改变值,请不要使用可变对象。

    如果您必须使用 Bar 对象,那么制作只有您引用的副本可能是解决此问题的最佳方法。

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2013-11-23
      • 2011-11-30
      • 2020-01-21
      • 2012-12-08
      • 2016-07-19
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多