【问题标题】:C++ set/get methods synchronizationC++ 设置/获取方法同步
【发布时间】:2015-09-06 08:58:00
【问题描述】:

让我们在 C++ 中考虑这样一个类:

class CuteClass
{
public:
  int    getFancyInt() const;
  float  getNiceFloat() const;
  string getPerfectString() const;

  void setIntSomething(int something);
  void setInternalState(State newState);
};

这个类的实例可以从几个不同的线程同时访问。然后:

所有 getMethods(getFancyInt、getNiceFloat、getPerfectString)不应相互阻塞。它们不会改变对象的内部状态。

所有的 setMethod(setIntSomething, setInternalState) 应该:

  • 互相阻止 - 避免对象状态不一致,
  • 阻止所有 getMethods - 以避免返回部分更改的数据,
  • 被所有 getMethods 阻止 - 以避免返回部分更改的数据。

带有互斥锁的简单 lock_guard 将满足除一个之外的所有要求 - getMethod 然后会阻止其他 getMethods。

在这种情况下,哪种解决方案既简单又干净?

【问题讨论】:

标签: c++ c++11 concurrency mutex


【解决方案1】:

您正在寻找的是 R/W 互斥锁。

您在所有 getter 中将其锁定为“READ”,在所有 setter 中将其锁定为“WRITE”。

Boost shared_mutex 就是你要找的东西

Example for boost shared_mutex (multiple reads/one write)?

为了与您的“const”声明兼容,您需要将互斥锁本身声明为可变

【讨论】:

  • 从 C++17 开始,我们还将拥有 std::shared_mutex
【解决方案2】:

std::atomic 应该解决有关部分更改数据的任何问题。

[编辑:]不,它没有。如果我不删除这个错误的答案,那只是为了应该保留有见地的 cmets。

【讨论】:

  • Atomic 仅在内部基本类型的情况下才是有效的解决方案。对于复杂类型或多个类型,您仍然可以有竞争条件
  • std::atomic 也适用于用户定义的类型,但可能涉及锁定。
  • 这并没有解决对象在读取时保持一致的内部状态。见OP点block all getMethods - to avoid returning partially changed data
  • std::atomic 对此问题的粒度错误。例如,setInternalState 可以很好地以原子方式修改“fancy int”,然后以原子方式修改“fancy float”。但这还不够。您想锁定整个事件序列,这样客户端在修改浮点数之前永远不会看到int的修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多