c ++可变关键字对线程有害吗?

时间:2011-01-07 18:04:56

标签: c++ multithreading

根据我对mutable关键字的理解,其主要用途之一是缓存数据并在需要时对其进行计算。既然它们可以改变(即使它们是常量),使用它们不是不安全或没有意义吗?缓存部分修改数据,因此需要锁定,根据我的理解,当您为多线程编写时,数据应该永远不会更改,并且应该复制并返回/链接在一起。

使用C ++的mutable关键字是没有意义的还是坏的?

3 个答案:

答案 0 :(得分:15)

  

使用C ++的mutable关键字是没有意义的还是坏的?

没有; mutable关键字是一件好事。 mutable可用于将对象的可观察状态与对象的内部内容分开。

使用您描述的“缓存数据”示例(mutable的一种非常常见的用法),它允许类“实际上”执行“实际上不会修改可观察状态的优化”。

关于从多个线程访问对象,是的,你必须要小心。通常,如果一个类被设计为从多个线程访问并且它具有mutable个变量,那么它应该在内部同步这些变量的修改。但请注意,问题实际上更像是一个概念问题。理由很简单:

  1. 我的所有线程只调用此共享对象上的const成员函数
  2. Const成员函数不会修改名为
  3. 的对象
  4. 如果未修改对象,则无需同步对其的访问
  5. 因此,我不需要同步对此对象的访问
  6. 这个参数是错误的,因为(2)是假的:const成员函数确实可以修改可变数据成员。问题在于,认为这个论点是正确的,真的很容易。

    解决这个问题的方法并不容易:实际上,在编写多线程代码时必须非常小心,并且绝对确定您了解如何实现线程之间共享的对象或者它们提供的并发性保证。< / p>

答案 1 :(得分:8)

另一方面,我的大多数多线程代码需要使用mutable关键字:

class object {
   type m_data;
   mutable mutex m_mutex;
public:
   void set( type const & value ) {
      scoped_lock lock( m_mutex );
      m_data = value;
   }
   type get() const {
      scoped_lock lock( m_mutex );
      return m_data;
   }
};

get方法未修改object状态的事实是通过const关键字声明的。但是,如果mutable修饰符未应用于mutex属性的声明,则代码将无法锁定或释放互斥锁 - 这两项操作都明确修改 {{ 1}},即使他们没有修改mutex

只要你锁定对象,你甚至可以使object属性变得可变,如果它可以被延迟评估并且成本很高。这是您在问题中引用的缓存用法。

只有当您尝试执行无锁多线程时,data修饰符才是多线程代码的问题。与所有无锁编程一样,无论mutable还是const,您都必须非常小心操作。您可以编写完全不安全的多线程代码,在没有mutable属性的对象上调用const方法。简单的例子是从前面的代码中删除互斥锁,并且N个线程只执行mutable s而另一个线程执行get() s。 set()是const的事实并不能保证如果另一个线程正在修改,你将不会得到无效的结果。

答案 2 :(得分:2)

不,mutable关键字是这样的,即使对象是const,您也可以在对象内部拥有可以更改的字段,例如对于不属于对象属性但是其管理(例如计数器等)的元数据)。它与线程无关。