通过 std::shared_ptr<T>::reset() 进行同步销毁
Synchronous destruction through std::shared_ptr<T>::reset()
考虑以下简化的程序建模一个真实的场景,其中不同的用户可以并发请求相同的资源:
#include <thread>
#include <memory>
#include <mutex>
#include <iostream>
using namespace std;
struct T {
void op() { /* some stuff */ }
~T() noexcept { /* some stuff */ }
};
std::shared_ptr<T> t;
std::mutex mtx;
std::weak_ptr<T> w{t};
enum action { destroy, op};
void request(action a) {
if (a == action::destroy) {
lock_guard<mutex> lk{mtx};
t.reset();
std::cout << "*t certainly destroyedn";
} else if (a == action::op) {
lock_guard<mutex> lk{mtx};
if (auto l = w.lock()) {
l->op();
}
}
}
int main() {
// At some point in time and different points in the program,
// two different users make two different concurrent requests
std::thread th1{request, destroy}; std::thread th2{request, op};
// ....
th2.join();
th1.join();
}
我并不是在问程序是否在形式上是正确的——我认为它是正确的,但是我从来没有见过这种方法保证通过智能指针共享的资源的同步销毁。我个人认为它很好,有一个有效的用途。
然而,我想知道其他人是否也这么想,如果有的话,除了与unique_lock
s和条件变量的经典同步以及引入对T
的修改(例如原子标志)之外,是否有更优雅的替代方案。
mtx
,那将是理想的。很好。shared_ptr中的引用计数是原子计数,并且锁定的副本在操作期间保持在作用域中,因此在操作期间不能销毁对象。
在这种情况下,互斥锁实际上并没有保护T的生命周期,而是对op()
的调用和销毁进行排序。如果你不介意多个并发调用op()
,或者销毁时间不确定(即在最后运行的op()
完成之后),那么你可以取消它,因为std::shared_ptr<>::reset()
和std::weak_ptr<>::lock()
都是线程安全的。
然而,我建议谨慎,因为作者明确表示要序列化对op()
的调用。
相关文章:
- 松弛原子与无同步情况下的记忆连贯性
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中同步线程
- 与 stdio 同步是否使程序 I/O 非交互式?
- unique_ptr:在分配之前调用 reset 有什么效果
- 如何在qt中同步应用程序和显示器的刷新率?
- Windows 进程间同步类似事件?
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 将 10 个线程与原子布尔值同步
- ofstream::close() 是否在 Linux 上调用同步?
- 与Visual Studios(c ++)同步时如何组织github存储库?
- 原子获取是否与互斥锁释放同步?
- Boost (Beast) websocket:同步写入挂起
- Postgres vs MySQL:命令不同步;.
- 线程过程中的线程同步问题
- 同步读取多个 TCP 响应
- 同步两个具有不同帧速率的传感器
- 如何定期同步线程?
- 同步对多个向量进行排序
- 通过 std::shared_ptr<T>::reset() 进行同步销毁