C++ c+中的共享ptr和内存可见性+;

C++ c+中的共享ptr和内存可见性+;,c++,multithreading,synchronization,C++,Multithreading,Synchronization,如果在线程A上使用shared_ptr堆分配对象,则将shared_ptr复制到另一个线程,而不进行任何同步。另一个线程是否保证看到完全构造的对象 int main(){ auto sp = std::make_shared<int>(5); auto f=std::async(std::launch::async, [sp](){ std::cout<<*sp;}); } intmain(){ 自动sp=std::使_共享(5); 自动f=st

如果在线程A上使用
shared_ptr
堆分配对象,则将
shared_ptr
复制到另一个线程,而不进行任何同步。另一个线程是否保证看到完全构造的对象

int main(){
    auto sp = std::make_shared<int>(5);
    auto f=std::async(std::launch::async, [sp](){
    std::cout<<*sp;});
}
intmain(){
自动sp=std::使_共享(5);
自动f=std::async(std::launch::async,[sp](){

std::cout在您的示例中,
shared_ptr
对象在
std::async
返回之前已被复制,因此即使原始共享_ptr在第二个线程访问其副本之前被销毁,它仍然存在于新线程中


因此,答案是肯定的。您是通过值传递的,因此是一个副本。

正如有人在评论中指出的那样,上面的特定场景(通过线程arg传递给新生成的线程的指针访问堆分配的对象)包含在这个问题的答案中


现在,对于您在中描述的场景(heap-allocated object是通过指向队列的指针在单独的线程中访问的),工作线程保证看到“5”,因为队列必须以线程安全的方式实现,内存屏障可以确保heap对象中存储的值的可见性(在您的情况下,互斥在幕后使用内存屏障)。

多线程环境中不同步=不保证…当您说“然后将内存地址复制到另一个线程”时,您的意思是线程已经运行时?还是说“然后用该内存地址构造线程”(这就是您的示例所示)?如果在分配值后调用std::async(如您的示例)然后在调用std::async之前分配它,它就会工作-就像您将它传递给任何其他函数一样。我不同意@OmidCompSCI..这个例子中的对象已经完全构造好了,共享指针是由lambda中的值捕获的。如果这不能保证工作,那么一切都会失控。@Evg The umalloc的se不会改变结果。线程创建是一个同步操作(是否需要内存屏障指令取决于硬件平台)这个例子中的线程仍然打印<代码> 5代码/>代码> @ EVG,这适用于任何<代码> STD::线程< /Cord>创建。如果创建对象<代码> x<代码>,然后创建一个线程,同时将代码> x<代码>到该线程,则完全同步。C++相关标准中的相关部分并不意味着生命的时间。我知道那里有没有生命周期问题。我的问题是关于内存可见性。5是否保证在主存而不是CPU缓存中?为什么用户级应用程序会关心这个问题?毕竟,编译器可能会在内部使用寄存器存储整数,而根本不使用内存。此外,你的问题并不能说明你对cac感兴趣如果是这样,请将asm标记放在缓存中。如果另一个线程在另一个CPU内核上运行,则该线程无法访问该值。编译器不可能不确保复制的值实际复制到内存中。如果这是真的,则整个多线程过程都会崩溃。是的,复制了共享线程,但复制了它所指向的对象ts to未被复制