假设我有一个简单的 A 类,在 C++ 中有一个字段。该字段在构造函数中初始化。A 类也有一个doit()
用于修改该字段值的方法。doit()
将从多个线程调用。如果我只在doit()
方法中有一个互斥锁,这就足够了吗?我是否可以保证永远不会读取未初始化的字段(因为构造函数中没有锁)?
编辑:我可能还不够清楚。没有涉及处理器缓存或类似问题的问题吗?我的意思是,如果没有用于初始化内存区域(即我的字段)的互斥锁 - 是否没有其他线程会读取一些垃圾值的风险?
您的对象只能初始化一次,并且在初始化之前您将无法使用它,因此您不需要在那里使用互斥锁。但是,您将需要在您的函数中使用互斥锁或其他合适的锁DoIt
,正如您所说,这将跨多个线程访问。
已编辑问题的更新:不,您无需担心处理器缓存。您必须先构造您的对象,然后才能拥有它的句柄。只有拥有此句柄后,才能将其传递给其他线程以供使用。我想说的是,产生的线程必须在原始对象构建之后开始,它不可能反过来发生!
无法调用doit()
尚未创建的对象,因此您不需要在构造函数中使用互斥锁。
如果doit()
是访问该字段的唯一方法,那么您应该没问题。
如果您的类的其他方法也访问该字段,即使是从单个线程,那么您也必须在这些方法中使用互斥锁。
或者,如果您了解各种方法与各种算法的交互,您可以对使用该字段的代码的关键部分使用互斥锁——即,该部分代码需要确保该字段在执行期间不会被另一个线程更改。处理,但你的方法可以在临界区之后释放锁,做其他事情然后可能有另一个临界区。