当C ++ const方法同步可变状态时,非const方法也必须这样做吗?

时间:2016-05-25 23:30:03

标签: c++ multithreading c++11 thread-safety

根据Herb Sutter(http://foo.bar.com:8000),在C ++ 11中,const方法不能逐位改变对象,或者如果它们具有可变数据成员,则必须执行内部同步(例如使用互斥)。 / p>

我的问题是,非const方法是否也必须获取互斥锁?或者,如果用户想要同时在同一个对象上混合const和非const方法,他们是否可以依赖用户必须执行的外部同步?

编辑:换句话说,是以下类的线程安全吗?下面的类是否提供了Sutter"基本的线程安全保证" (来自http://isocpp.org/blog/2012/12/you-dont-know-const-and-mutable-herb-sutter)?

#include <thread>

class C {
  public:
  void const_method() const
  {
    std::lock_guard<std::mutex> g(m);
    i = 2;
  }

  void non_const_method()
  {
    // std::lock_guard<std::mutex> g(m); // <-- is this needed?
    i = 1;
  }

  private:
  mutable int i;
  mutable std::mutex m;
};

2 个答案:

答案 0 :(得分:4)

不,你的班级本身并不是线程安全的。

void non_const_method()
{
    // std::lock_guard<std::mutex> g(m); // <-- is this needed?
    i = 1;
}

以上不是线程安全的,因为多个线程可以调用该函数,从而同时改变i

所以回答:

  

以下课程是否提供了Sutter&#34;基本的线程安全保障&#34;

然后是的,该类提供了基本的线程安全保证&#34;。您无法从另一个实例修改一个实例,并且该类的const方法是线程安全的。

您必须使用某种外部同步才能在多个线程中的同一实例上使用该类的可变函数,但您的非可变函数不需要外部同步。

答案 1 :(得分:0)

理想情况下, writer 需要获得比 reader 更严格的锁定。您可能已经争论过读者是否需要获得锁定(但您提出了另一种方式)。作家更多的是造成数据不一致的原因。

通过严格锁定,我的意思是在锁定协议中可以读取锁定和写入锁定 - 然后编写器锁定会更严格。在大多数实现中,获得写入锁定的线程会阻止所有其他线程获得任何类型的锁定,但是可以同时获取读取器锁定。因此,非const函数理想情况下会使用writer-lock,但const函数可能只需要读取器锁定 - 从而允许并行执行相同的函数(或同一对象的类似const函数)

是的,锁定协议可能不会优先于 writer 线程等待 reader 线程等待。但是,这个实现细节。