Closed 。这个问题需要多问focused 。目前不接受答案。
如何确保新构造的不可变对象可以在 C++ 线程之间安全共享? C++ 内存模型是否为构造函数的操作提供保证?
当多个线程共享对某个对象的访问并且该对象被修改时,可能会出现竞争危险。这些问题可以通过以下方式避免安全发布 该对象传递给所有线程(包括所有可能的未来线程),因此从任何线程对该对象的所有后续访问都会看到相同的对象状态,然后避免修改该对象。如果不使用锁(互斥体),后续对该对象的访问将不会受到竞争危险的影响。在极端情况下,该对象是不可变的 : 一旦构建,就永远不会改变。因此,有一种习惯用法是在多线程程序中尽可能使用不可变对象。
这仍然需要在构造函数中的代码执行后安全地发布对象。例如,构造函数执行的代码将值分配给内存位置,但这些写入的值可能(最初)仅存在于 CPU 的本地缓存中。访问这些内存位置的其他线程可能会看到记录在这些内存位置的旧值(例如由malloc
, 例如)。对于新构造的对象所覆盖的内存位置,必须有一种机制来刷新本地缓存并使其他 CPU 的缓存无效。
在对高级可移植编程语言(如 C++)进行编程时,您不必关心缓存和缓存刷新的细节。相反,该语言提供了一组保证(内存模型),您必须根据一些习惯用法编写代码才能可靠地实现您的目标。
在Java中,这是自动地 通过遵循类设计中的一些规则来完成(过度简化:做一切final ,即有点像const in C++ ),Java内存模型保证会产生预期的效果。这可以通过在执行构造函数的代码后立即设置内存屏障来实现。
在 C++11 中这是如何完成的? C++ 内存模型是否提供有关构造函数操作的保证,使您能够自动发布新构造的对象?如果是这样,你们的课程规则是什么?如果没有,你必须自己添加一个内存屏障(如你显然必须为.Net做 ),是否有一种习惯用法可以在构造后有效地发布对象?
或者C++11不提供对不可变对象的线程安全无锁访问?您必须使用互斥锁来保护对共享对象(无论是否不可变)的所有访问吗?
主要有两种情况:
读取线程的创建是有序的——在对象创建之后
读取线程的创建是not 在创建对象之后排序
在情况 1 中,对对象的读取访问自动是安全的,因为线程中的读取是在线程本身创建之后有序进行的。
在情况 2 中,您必须以某种方式对读取进行排序,这正是因为线程创建不提供顺序。很明显,如果在创建对象之后读取没有排序,那么事情就会出错。
您的问题想了解 CPU 缓存等详细信息。这是编译器编写者关心的问题。您只需遵守 C++ 排序规则即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)