C++ 将指针传递到共享线程安全 //示例程序 #包括 #包括 #包括 #包括 结构Smth{}; 线程2中使用的结构B{// B(std::shared_ptr*smth):smth_(smth){}; ~B(); 无效剂量测定法(){ std::shared_ptr newSmth=std::make_shared(); smth->swap(新MTH); } std::共享的ptr*smth; }; 线程1和3中使用的结构A{// A():smth_u0;(std::make_shared()),b_0;(&smth_0;){}; ~A(); std::共享ptr smth; B B_; };

C++ 将指针传递到共享线程安全 //示例程序 #包括 #包括 #包括 #包括 结构Smth{}; 线程2中使用的结构B{// B(std::shared_ptr*smth):smth_(smth){}; ~B(); 无效剂量测定法(){ std::shared_ptr newSmth=std::make_shared(); smth->swap(新MTH); } std::共享的ptr*smth; }; 线程1和3中使用的结构A{// A():smth_u0;(std::make_shared()),b_0;(&smth_0;){}; ~A(); std::共享ptr smth; B B_; };,c++,multithreading,thread-safety,shared-ptr,stdatomic,C++,Multithreading,Thread Safety,Shared Ptr,Stdatomic,那么,将指针传递给shared_ptr,这样我就可以在单独的线程中交换shared_ptr的内容,这是一种好的做法吗? 第二个问题是,我是否应该使用std::atomic_store来替换共享的\u ptr::swap,如果是这样,我应该怎么做?我的想法让人难以置信,你可能最终选择了这个设计。。。我希望这在你真正的项目中是有意义的 您应该向共享\u ptr传递指针(最好是引用)的唯一原因是重新定位它(正如您正在做的),并且您不需要同步交换本身(共享\u ptr已经同步) 但是,交换内容将导致与当

那么,将指针传递给shared_ptr,这样我就可以在单独的线程中交换shared_ptr的内容,这是一种好的做法吗?
第二个问题是,我是否应该使用std::atomic_store来替换共享的\u ptr::swap,如果是这样,我应该怎么做?

我的想法让人难以置信,你可能最终选择了这个设计。。。我希望这在你真正的项目中是有意义的

您应该向
共享\u ptr
传递指针(最好是引用)的唯一原因是重新定位它(正如您正在做的),并且您不需要同步交换本身(
共享\u ptr
已经同步)

但是,交换内容将导致与当时正在使用对象(读取或写入)的其他线程的同步问题。因此,如果两个线程都在修改对象,则需要应用相同的同步技术

对我来说,这并不是一个解决任何实际问题的可靠方案。也许考虑将一个新的<代码> STD::SysDypPTR <代码>到另一个线程,然后发出信号,这样它就知道拿起新的共享指针(由复制而不是指针)。

< P>与(一些)传统的智慧相反,<代码> SydDypTr> /Cord>对象本身是强>不是线程安全< /强>。也就是说,您不能在不同的线程上同时操作单个
shared_ptr
对象,就像您不能同时操作
std::vector
std::string
或具有“默认”线程安全性的任何其他标准库对象一样

出现这种混淆是因为典型的
shared_ptr
确实使用原子操作来操纵其引用计数,但这只是为了支持不同
shared_ptr
对象指向同一底层对象(从而共享引用计数)的场景

这种隐藏共享与以前在
std::string
的COW实现中发生的情况相同:如果不锁定,您永远无法在不同线程上安全地操作相同的
std::string
对象,但是COW行为意味着,如果没有原子操作,您甚至无法操作两个不同的
std::string
对象,它们恰好在不同的线程上共享相同的底层缓冲区,这违反了
std::string
对象的值语义和标准库线程安全保证。因此,在实践中,您有原子操作来操作COW缓冲区引用计数,但其他操作都是以非线程安全的方式编写的

因此,底线是,像这样共享
shared_ptr
可能不仅是一个糟糕的设计:它是明确不允许的,因为它不是线程安全的



1这里的并发操作意味着访问多个线程上的
共享\u ptr
对象,其中至少有一些访问是对非
const
方法的。标准库提供了一个通用的保证,即仅由
const
-方法访问组成的并发访问是安全的(即,
const
从线程角度作为操作为“只读”的标志)

指向智能指针的指针听起来像是拙劣的设计。是的,您需要原子或锁来保护对共享资源的访问,<代码> Sththi。考虑函数<代码> STD::AddixIX Exchange <代码> >代码> STD::SyrdYPPTR < /C>,@ Vu1P3N0x:<代码> SydDypTr> /Cord>不可复制,所以不能使用<代码>原子< /代码>。
shared_ptr
实例指向的ref count块具有原子计数器,但
shared_ptr
本身不是线程安全的。@PeterCordes我指的不是
atomic
,而是可以使用我链接的
shared_ptr
调用的原子操作,以If多线程开头的措辞不清楚,但我相信它意味着以下(不相交的)跨线程场景是安全的(a)所有访问都是通过
const
限定的成员函数,或者(b)所有访问都是通过这些
std::atomic…
重载进行的。我认为它们并不意味着可以安全地将
const
限定访问和这些原子重载结合使用。线程2是一个定期配置检索器。其他线程直接使用结构A。因此,您建议我在结构B中实现方法getConfig,该方法根据需要将当前共享\u ptr的副本直接返回给其他线程?@user2207495,以便其他线程持有指向同一
结构A
对象的指针?或者他们每个人都有自己的
结构,一个包含原始
共享ptr
副本的
对象?@user2207495需要注意的一件事是,重置
共享ptr
只会重置您持有引用的单个
共享ptr
。原始
共享\u ptr
的所有其他副本将不受影响,并继续指向原始对象。@user2207495我的直觉(不知道您的情况)是您需要使用(同步)值副本替换指向的对象,而不是操纵指针。因此,每个线程都使用一个(复制的)
shared_ptr
指向同一个对象,当它需要更改时,您可以使用一个新的副本(在同步下)覆盖该对象。很抱歉,响应速度太慢,其他线程持有指向同一个对象结构的指针。我需要存储其他线程的全局配置。什么时候
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <atomic>

struct Smth {};

struct B { //Used in thread 2
    B(std::shared_ptr<Smth>* smth) : smth_(smth) {};
    ~B();
    void DoSomething() {
        std::shared_ptr<Smth> newSmth = std::make_shared<Smth>();
        smth_->swap(newSmth);
    }
    std::shared_ptr<Smth>* smth_;
};

struct A { //Used in thread 1&3
  A() : smth_(std::make_shared<Smth>()), b_(&smth_) {};
  ~A();
  std::shared_ptr<Smth> smth_;
  B b_;
};