我是否需要在字段的构造函数中互斥锁

Do I need mutex in constructor for field?

本文关键字:构造函数 字段 是否      更新时间:2023-10-16

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

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

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

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

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

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

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

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

或者,如果您了解各种方法与各种算法的交互,则可以对使用该字段的关键代码部分使用互斥锁 - 即该部分代码需要确保该字段在处理过程中不会被另一个线程更改,但您的方法可以在关键部分之后释放锁, 做点别的事情,然后也许有另一个关键部分。