shared_ptr的引用计数操作线程安全,但其管理的对象及shared_ptr实例本身的并发修改需额外同步。多个线程可安全拷贝或销毁shared_ptr,因引用计数增减为原子操作;但若多线程读写shared_ptr指向的对象,则必须通过互斥锁等机制保证对象数据一致性;此外,当多个线程对同一shared_ptr变量进行赋值、重置时,该变量本身的修改非原子,C++20前需用mutex保护,C++20起可使用std::atomic<std::shared_ptr<T>>实现原子操作;weak_ptr::lock()线程安全,适合多线程中安全检查对象存活性。

shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
要安全地在多线程环境中使用
shared_ptr
理解shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
保护shared_ptr
shared_ptr
shared_ptr
立即学习“C++免费学习笔记(深入)”;
std::mutex
shared_ptr
shared_ptr
保护shared_ptr
shared_ptr
std::shared_ptr<T> current_resource;
shared_ptr
std::atomic<std::shared_ptr<T>>
shared_ptr
std::mutex
shared_ptr
weak_ptr
weak_ptr
shared_ptr
weak_ptr::lock()
shared_ptr
lock()
shared_ptr
weak_ptr
shared_ptr
是的,
shared_ptr
shared_ptr
shared_ptr
shared_ptr
然而,它的安全边界非常明确且有限。这种线程安全仅限于引用计数器本身。它不延伸到
shared_ptr
std::shared_ptr<MyData> ptr;
MyData
int counter;
ptr->counter++
counter++
shared_ptr
MyData
另一个需要注意的边界是,这种原子性也不扩展到shared_ptr
std::shared_ptr<MyData> global_ptr;
global_ptr = std::make_shared<MyData>();
global_ptr = nullptr;
global_ptr
global_ptr
global_ptr
shared_ptr
确保
shared_ptr
shared_ptr
shared_ptr
内部互斥锁(Mutex Guard): 这是最直接、最常用的方法。将一个
std::mutex
MyObject
MyObject
class MyThreadSafeObject {
public:
void updateData(int value) {
std::lock_guard<std::mutex> lock(mtx_); // 锁定互斥量
data_ = value;
// ... 其他数据操作
}
int getData() const {
std::lock_guard<std::mutex> lock(mtx_); // 锁定互斥量
return data_;
}
private:
mutable std::mutex mtx_; // 使用mutable允许const成员函数锁定
int data_ = 0;
};
// 使用
std::shared_ptr<MyThreadSafeObject> sharedObj = std::make_shared<MyThreadSafeObject>();
// 多个线程可以安全地调用 sharedObj->updateData() 和 sharedObj->getData()通过这种方式,
MyThreadSafeObject
shared_ptr
Raza Microelectronics, Inc.(RMI公司)是勇于创新的信息基础架构半导体解决方案领导厂商,其产品广泛地被应用于改善不断演进的信息基础设施。在这个演进过程中,数据中心和家庭之间的连接在强度和速率方面都逐渐升级;安全和智能化已经成为每一个网络系统环境的要求;同时,边缘网络日益成为瓶颈,促使业界需要更具扩展能力及成本优势的智能网络接入方法。RMI公司为信息基础架构设计并提供多样化的解决方案,为下一代灵活的企业和数据中心应用、智能接入和数字影像系统奠定基础。 RMI远程方法调用目录 一、
0
不可变对象(Immutable Objects): 如果你的设计允许,让
shared_ptr
const
class MyImmutableData {
public:
MyImmutableData(int id, const std::string& name) : id_(id), name_(name) {}
int getId() const { return id_; }
const std::string& getName() const { return name_; }
// 没有setter方法
private:
const int id_;
const std::string name_;
};
// 使用
std::shared_ptr<const MyImmutableData> sharedImmutableData = std::make_shared<const MyImmutableData>(1, "Test");
// 多个线程可以安全地读取 sharedImmutableData 的数据读写锁(Shared Mutex / std::shared_mutex
std::shared_mutex
boost::shared_mutex
#include <shared_mutex> // C++17
class MyReadWriteObject {
public:
void updateData(int value) {
std::unique_lock<std::shared_mutex> lock(mtx_); // 独占锁
data_ = value;
}
int getData() const {
std::shared_lock<std::shared_mutex> lock(mtx_); // 共享锁
return data_;
}
private:
mutable std::shared_mutex mtx_;
int data_ = 0;
};外部同步: 如果你无法修改被管理的对象(例如,它来自第三方库),或者你认为对象内部同步会过于复杂,那么你可以在所有访问该对象的代码块外部使用一个全局或局部的
std::mutex
shared_ptr
// 假设MyExternalObject不是线程安全的
class MyExternalObject { /* ... */ };
std::shared_ptr<MyExternalObject> global_obj = std::make_shared<MyExternalObject>();
std::mutex global_obj_mutex;
void thread_func() {
std::lock_guard<std::mutex> lock(global_obj_mutex);
// 安全地访问 global_obj
// global_obj->some_method();
}选择哪种方法取决于对象的特性、访问模式以及对性能的要求。通常,内部互斥锁或不可变对象是更健壮和易于维护的选择。
shared_ptr
我们已经知道
shared_ptr
shared_ptr
shared_ptr
这主要发生在当一个
shared_ptr
shared_ptr
shared_ptr
考虑以下场景:
共享的配置指针: 你的应用程序可能有一个全局的
shared_ptr<Config> current_config;
Config
current_config
std::shared_ptr<Config> current_config; // 全局或共享的shared_ptr
void update_config_thread() {
auto new_config = std::make_shared<Config>(/* new parameters */);
// 在这里,对 current_config 的赋值操作需要保护
current_config = new_config;
}
void read_config_thread() {
// 读取 current_config 也需要保护,以获取一致的视图
std::shared_ptr<Config> local_config = current_config; // 拷贝操作
// 使用 local_config
}在这种情况下,
current_config = new_config;
current_config
资源池中的元素替换: 比如一个
shared_ptr<Connection> active_connection;
nullptr
解决方案:
C++20及更高版本:使用std::atomic<std::shared_ptr<T>>
std::atomic<std::shared_ptr<T>>
shared_ptr
#include <atomic> // C++20
std::atomic<std::shared_ptr<Config>> current_config_atomic;
void update_config_atomic_thread() {
auto new_config = std::make_shared<Config>(/* new parameters */);
current_config_atomic.store(new_config); // 原子赋值
}
void read_config_atomic_thread() {
std::shared_ptr<Config> local_config = current_config_atomic.load(); // 原子加载
// 使用 local_config
}C++17及以前版本:使用std::mutex
std::mutex
shared_ptr
std::shared_ptr<Config> current_config_legacy;
std::mutex config_mutex;
void update_config_legacy_thread() {
auto new_config = std::make_shared<Config>(/* new parameters */);
std::lock_guard<std::mutex> lock(config_mutex);
current_config_legacy = new_config; // 赋值操作在锁保护下进行
}
void read_config_legacy_thread() {
std::shared_ptr<Config> local_config;
{
std::lock_guard<std::mutex> lock(config_mutex);
local_config = current_config_legacy; // 拷贝操作在锁保护下进行
}
// 使用 local_config
}记住,这里保护的是
shared_ptr
Config
Config
shared_ptr
shared_ptr
以上就是C++shared_ptr与多线程环境安全使用方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号