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

6 c++ multithreading

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

那么使用C++的可变关键字是没有意义的还是坏的?

Jam*_*lis 15

那么使用C++的可变关键字是没有意义的还是坏的?

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

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

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

  1. 我的所有线程只调用此共享对象上的const成员函数
  2. Const成员函数不会修改调用它们的对象
  3. 如果没有修改对象,我不需要同步对它的访问
  4. 因此,我不需要同步访问此对象

这个参数是错误的,因为(2)是假的:const成员函数确实可以修改可变数据成员.问题在于,认为这个论点是正确的,真的很容易.

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

  • @Charles:嗯,我认为可以说这是"可变"数据成员的问题.如果你有一些对共享对象有const引用的线程,那么假设你可以在没有任何同步的情况下调用这些const成员函数通常是合理的.很容易忘记mutable并错误地认为const成员函数根本不能改变底层状态. (2认同)

Dav*_*eas 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;
   }
};
Run Code Online (Sandbox Code Playgroud)

通过关键字声明get方法不修改状态的事实.但是,如果没有应用到的声明修改属性,代码将无法锁定或者释放互斥锁--both操作明确修改的,即使他们不修改.objectconstmutablemutexmutexobject

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

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

  • @Niki:根据我的个人经验,这完全是有偏见的,我从未遇到过 RWLock 是更好的解决方案的情况。我遇到过这样的情况,它更好,但在努力减少关键部分大小之后,普通互斥体最终成为更好的解决方案。测量一下,您的里程可能会有所不同。但出于充分的理由,我已经在我使用的代码库中删除了相当数量的 RWLock。这是我的个人经验,RWLock *听起来*很棒,但它们并不是*那么*好。 (2认同)