8

假设我有一个简单的 A 类,在 C++ 中有一个字段。该字段在构造函数中初始化。A 类也有一个doit()用于修改该字段值的方法。doit()将从多个线程调用。如果我只在doit()方法中有一个互斥锁,这就足够了吗?我是否可以保证永远不会读取未初始化的字段(因为构造函数中没有锁)?

编辑:我可能还不够清楚。没有涉及处理器缓存或类似问题的问题吗?我的意思是,如果没有用于初始化内存区域(即我的字段)的互斥锁 - 是否没有其他线程会读取一些垃圾值的风险?

4

3 回答 3

7

您的对象只能初始化一次,并且在初始化之前您将无法使用它,因此您不需要在那里使用互斥锁。但是,您将需要在您的函数中使用互斥锁或其他合适的锁DoIt,正如您所说,这将跨多个线程访问。

已编辑问题的更新:不,您无需担心处理器缓存。您必须先构造您的对象,然后才能拥有它的句柄。只有拥有此句柄后,才能将其传递给其他线程以供使用。我想说的是,产生的线程必须在原始对象构建之后开始,它不可能反过来发生!

于 2012-10-12T10:42:33.263 回答
2

无法调用doit()尚未创建的对象,因此您不需要在构造函数中使用互斥锁。

如果doit()是访问该字段的唯一方法,那么您应该没问题。

如果您的类的其他方法也访问该字段,即使是从单个线程,那么您也必须在这些方法中使用互斥锁。

于 2012-10-12T10:45:41.123 回答
0
  1. 您首先需要在那些讨厌的线程得到它之前构造对象。操作系统将为仅由一个线程调用的构造函数分配内存。Ths OS 负责该分配,因此您无需执行任何操作。地狱,您甚至可以在两个不同的线程中创建同一类的两个对象。
  2. 您可以非常保守,并在使用该字段锁定它的任何方法的开头使用互斥锁,然后释放它并结束。

或者,如果您了解各种方法与各种算法的交互,您可以对使用该字段的代码的关键部分使用互斥锁——即,该部分代码需要确保该字段在执行期间不会被另一个线程更改。处理,但你的方法可以在临界区之后释放锁,做其他事情然后可能有另一个临界区。

于 2012-10-12T12:11:37.583 回答