C++内存模型是否对构造函数的操作提供保证?

3
如何确保在C++中新构造的不可变对象在线程之间安全共享?C++内存模型是否提供有关构造函数操作的保证?
当您有多个共享访问对象的线程,并且对象被修改时,可能会出现竞争条件。可以通过将对象“安全发布”到所有线程(包括所有可能的未来线程),以便从任何线程对对象的所有后续访问看到相同的对象状态,然后避免修改对象来避免这些问题。在没有使用锁(互斥体)的情况下,后续对对象的访问将不受竞争条件的影响。在极端情况下,该对象是不可变的:一旦构造,就不再改变。因此,在多线程程序中尽可能地使用不可变对象的习惯用法存在。
这仍然需要在构造函数执行代码后安全地发布对象。构造函数执行的代码将值分配给内存位置,但这些写入的值可能(最初)仅存在于CPU的本地缓存中。其他访问这些内存位置的线程可能会看到旧值,这些旧值记录在这些内存位置上(例如,由malloc设置的0x00字节模式)。必须有一种机制来刷新本地缓存并使其他CPU的缓存失效,以覆盖新构造的对象所涵盖的内存位置。
当使用高级便携式编程语言(如C ++)进行编程时,您不必关心缓存和缓存刷新的详细信息。相反,该语言提供了一组保证(内存模型),您必须根据某些习惯用法编写代码以可靠地实现您的目标。
在Java中,这是通过遵循类设计中的一些规则(简化来说:使所有内容final,这有点像C++中的const自动完成的,Java内存模型保证会产生期望的效果。这可能是通过在构造函数代码执行后立即设置内存屏障来实现的。
在C++11中如何实现呢?C++内存模型是否提供有关构造函数操作的保证,使您能够自动发布新构造的对象?如果是这样,那么您类的规则是什么?如果不是,而且您必须自己添加内存屏障(就像.Net一样),那么是否有一种习惯用法可以在构造后高效地发布对象?
或者C++11没有提供对不可变对象的线程安全无锁访问?必须使用互斥锁来保护对共享对象(不管是不是不可变的)的所有访问吗?

可能相关的阅读材料:http://en.cppreference.com/w/cpp/atomic/memory_order - Jesper Juhl
2
C++不允许在不同线程中同时进行非同步访问的情况下修改对象。除此之外,其他操作都是可以的。如果没有人更改对象,则每个人都可以安全地访问它。显然,在对象正在构建时,从不同的线程访问它是不可取的。 - n. m.
@n.m. “不允许”是什么意思 - 据我所知,没有语言机制可以阻止您这样做 - 它只是读取线程的未定义行为。 - R2RT
@n.m. Ye,我发表评论太快了,然后更新了它。我的观点是你的陈述听起来好像C++本身可以阻止你(检测到它,抛出异常等)同时进行读写,这意味着它具有内置的同步功能。我们都知道这不是真的。 - R2RT
我不认为这个问题的本质,“C++内存模型是否提供有关构造函数操作的保证?”太宽泛了。 - Raedwald
显示剩余4条评论
1个回答

0

有两种主要情况:

  1. 在创建对象之后,有序地创建读取线程
  2. 在创建对象之后没有有序地创建读取线程

在情况1中,由于线程的读取是在线程本身创建之后有序进行的,因此自动保证了对对象的读取访问安全。

在情况2中,您必须以某种方式对读取进行排序,正是因为线程创建不提供顺序。很明显,如果读取不是在对象创建之后有序进行的,那么事情就会出错。

您的问题涉及CPU缓存等细节。这是编译器编写者的关注点。您只需要遵守C++的排序规则即可。


在第2种情况下,你必须以某种方式对读取进行排序。是的,但是如何做到这一点呢?不是一般情况下,而是在新构建的对象的特定情况下?"你只需要遵守C++的排序规则" 是的,但是在这里有哪些相关规则呢? - Raedwald
@Raedwald:C++中有多种机制可以导致排序关系,并且它们可以组合使用(这种排序是传递的,因此A在B之前并且B在C之前意味着A在C之前)。这为您提供了相当多的选项。例如,std::mutexstd::condition_variable都提供跨线程排序保证。但是C++互斥锁没有线程优先级。它通常仅用于防止“同时发生”,而不关心哪个线程首先运行,例如当您有多个工作线程向vector添加值时。 - MSalters
那么,您是说构造对象不会引入任何读取顺序(不会自动插入内存屏障),因此您必须手动跟随对象的构造,使用引入读取顺序的操作(例如获取和释放互斥锁)? - Raedwald
1
@Raedwald 对象的构建在线程方面并没有什么特殊之处。它只是一系列的访问。 - n. m.
“对象构造在任何方面都不是特殊的”是至关重要的事情。 - Raedwald
顺便提一下,标准中使用的术语是“发生在之后”。 - Passer By

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接