传递指向shared_ptr线程安全的指针
Passing pointer to shared_ptr thread safety
// 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_;
};
那么,将指针传递给shared_ptr以便我可以在单独的线程中交换shared_ptr的内容是否是一种好的做法? 第二个问题是我应该使用 std::atomic_store 来替换 shared_ptr::swap,如果是这样,我应该怎么做?
我的想法是令人难以置信的,你最终会得到这个设计选择......我希望它在你的实际项目中是有意义的。
您应该将指针(或最好是引用)传递给shared_ptr
的唯一原因是重新放置它(就像您正在做的那样),并且您不需要同步交换本身(shared_ptr
已经同步)。
但是,交换内容将导致与当时使用该对象(读取或写入)的其他线程发生同步问题。因此,您需要应用与两个线程都在修改对象时相同的同步技术。
在我看来,这都不像是解决您实际问题的可靠解决方案。也许考虑将新std::shared_ptr
传递给另一个线程,然后发出信号,以便它知道拾取新的共享指针(通过复制而不是指针)。
与(一些)传统观点相反,shared_ptr
对象本身不是线程安全的。也就是说,您不能在不同线程上同时操作1个单个shared_ptr
对象,就像您不能同时操作具有"默认"线程安全性的std::vector
或std::string
或任何其他标准库对象一样。
出现混淆是因为典型的shared_ptr
确实使用原子操作来操作其引用计数 - 但这只是为了支持不同shared_ptr
对象指向同一基础对象(因此共享引用计数)的情况。
这种隐藏共享与过去发生在std::string
的 COW 实现中的事情相同:您永远无法在不锁定的情况下安全地操作不同线程上的相同std::string
对象,但 COW 行为意味着如果没有原子操作,您甚至无法操作两个不同的std::string
对象,它们恰好在不同线程上共享相同的底层缓冲区, 违反std::string
对象的值语义和标准库线程安全保证。因此,在实践中,您有原子操作来操作 COW 缓冲区引用计数,但其他操作像往常一样以非线程安全的方式编写。
所以底线是,共享这样的shared_ptr
可能不仅是一个糟糕的设计:它是明确不允许的,因为它不是线程安全的。
1此处并发操作意味着访问多个线程上的shared_ptr
对象,其中至少有一些访问是非const
方法。标准库提供了仅包含const
方法访问的并发访问是安全的(即,从线程角度来看,const
充当操作是"只读"的标志)。
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 如何以线程安全的方式更改目录?
- 线程安全的引用计数队列C++
- 析构函数和线程安全
- 适用于大型数组的无复制线程安全环形缓冲区