根据我对mutable关键字的理解,其主要用途之一是缓存数据并在需要时对其进行计算。既然它们可以改变(即使它们是常量),使用它们不是不安全或没有意义吗?缓存部分修改数据,因此需要锁定,根据我的理解,当您为多线程编写时,数据应该永远不会更改,并且应该复制并返回/链接在一起。
使用C ++的mutable关键字是没有意义的还是坏的?
答案 0 :(得分:15)
使用C ++的mutable关键字是没有意义的还是坏的?
没有; mutable
关键字是一件好事。 mutable
可用于将对象的可观察状态与对象的内部内容分开。
使用您描述的“缓存数据”示例(mutable
的一种非常常见的用法),它允许类“实际上”执行“实际上不会修改可观察状态的优化”。
关于从多个线程访问对象,是的,你必须要小心。通常,如果一个类被设计为从多个线程访问并且它具有mutable
个变量,那么它应该在内部同步这些变量的修改。但请注意,问题实际上更像是一个概念问题。理由很简单:
这个参数是错误的,因为(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,您也可以在对象内部拥有可以更改的字段,例如对于不属于对象属性但是其管理(例如计数器等)的元数据)。它与线程无关。