如何确保新构造的不可变对象在C++中的线程之间安全地共享?C++内存模型是否为构造函数的操作提供了保证?
当您有共享对对象的访问的多个线程,并且该对象被修改时,竞争危险是可能的。可以通过安全地将对象发布到所有线程(包括所有可能的未来线程)来避免这些问题,因此任何线程对对象的所有后续访问都会看到相同的对象状态,然后避免修改对象。对对象的后续访问不需要使用锁(互斥)就可以避免种族危险。在极端情况下,对象是https://stackoverflow.com/questions/622664/what-is-immutability-and-why-should-i-worry-about-it:一旦构造,它就永远不会改变。因此,在多线程程序中尽可能多地使用不可变对象是一种成语。
这仍然需要在构造函数中的代码执行之后安全地发布对象。构造函数执行的代码将值分配给内存位置,但是这些写入值(最初)可能只存在于CPU的本地缓存中,例如。访问这些内存位置的其他线程可能会看到在这些内存位置记录的旧值(例如,malloc设置的0x00字节的模式)。必须有一种机制来刷新本地缓存并使其他CPUS的缓存失效,以用于新构造的对象所覆盖的内存位置。
在编写高级可移植编程语言(如C++ )时,您不必考虑缓存和缓存刷新的细节。相反,该语言提供了一组保证(内存模型),您必须按照一些成语编写代码才能可靠地实现您的目标。
在Java中,这是通过遵循类设计中的一些规则(过度简化::final,即 in C++)自动实现的,Java内存模型保证这将产生预期的效果。这可以通过在执行构造函数的代码后立即设置一个内存屏障来实现。
这是如何在C++11中完成的?C++内存模型是否为构造函数的操作提供了保证,使您能够自动发布新构造的对象?如果是的话,您的课程有哪些规则?如果没有,而且您必须自己添加一个内存屏障(如you apparently have to do for .Net),那么是否有一个成语可以在构造后高效地发布对象?
还是C++11不提供对不可变对象的线程安全无锁访问?必须用互斥保护所有对共享对象(不可变或不可变)的访问?
发布于 2017-11-23 16:45:41
主要有两种情况:
在案例1中,对对象的读访问是自动安全的,因为线程中的读是在线程本身创建之后排序的。
在第二种情况下,您必须以某种方式对读取进行排序,这完全是因为线程创建没有提供顺序。很明显,如果读取没有被排序--在创建对象之后,事情就会出错。
你的问题是关于CPU缓存之类的细节的。这是编译器编写人员关心的问题。您只需遵守C++排序规则即可。
https://stackoverflow.com/questions/47459833
复制相似问题