正确的方法来创建thread_safe shared_ptr没有锁
Correct way to create thread_safe shared_ptr without a lock?
我正在尝试创建一个线程安全的shared_ptr类。我的用例是shared_ptr属于类的对象,并且行为有点像单例(CreateIfNotExist函数可以由任何线程在任何时间点运行)。
本质上,如果指针为空,第一个设置该值的线程获胜,并且同时创建该指针的所有其他线程都使用获胜线程的值。
这是我到目前为止所做的(注意,唯一有问题的函数是CreateIfNotExist()函数,其余的用于测试目的):
#include <memory>
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
struct A {
A(int a) : x(a) {}
int x;
};
struct B {
B() : test(nullptr) {}
void CreateIfNotExist(int val) {
std::shared_ptr<A> newPtr = std::make_shared<A>(val);
std::shared_ptr<A> _null = nullptr;
std::atomic_compare_exchange_strong(&test, &_null, newPtr);
}
std::shared_ptr<A> test;
};
int gRet = -1;
std::mutex m;
void Func(B* b, int val) {
b->CreateIfNotExist(val);
int ret = b->test->x;
if(gRet == -1) {
std::unique_lock<std::mutex> l(m);
if(gRet == -1) {
gRet = ret;
}
}
if(ret != gRet) {
std::cout << " FAILED " << std::endl;
}
}
int main() {
B b;
std::vector<std::thread> threads;
for(int i = 0; i < 10000; ++i) {
threads.clear();
for(int i = 0; i < 8; ++i) threads.emplace_back(&Func, &b, i);
for(int i = 0; i < 8; ++i) threads[i].join();
}
}
这样做正确吗?是否有更好的方法来确保所有线程调用CreateIfNotExist()在同一时间都使用相同的shared_ptr?
可以这样写:
struct B {
void CreateIfNotExist(int val) {
std::call_once(test_init,
[this, val](){test = std::make_shared<A>(val);});
}
std::shared_ptr<A> test;
std::once_flag test_init;
};
相关文章:
- C++长双大"safe"整数
- 有没有"safe" static_cast选择?
- 引用 std::shared:ptr 以避免引用计数
- 如何以" Safe "的方式获取 C++ 中的当前时间
- "thread-safe data"与"thread-safe code/functions"的区别
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- 无法使用 libtool 将 -shared 参数传递给 g++
- 链接 boost 库时"Error while loading shared libraries"引发的,除了我无法使用 root 访问权限来修复它
- 解决方法:'can not be used when making a shared object; recompile with -fPIC'使用Cmake。使用普通的 g++ 工作
- 是否有C++准则将第一个枚举设置为"safe"默认值?
- "Safe"将元素添加到 std::vector 的方法,超出了其 size() 但低于其容量 ()
- gcc -fPIC vs. -shared
- 在shared_from_this()中的错误类型(在继承类中)(是否有dyn.type-ware shared Poi
- 有没有一种"safe"方法来声明 lippincott 函数,这样它就不会在捕获之外被调用?
- "Error creating variant or safe array" in TClientDataSet.LoadFromStream() in Delphi
- "directory containing symbolic versions of my app's shared libraries"的位置(ndk-stack)
- Apache Thrift, Thread Safe TSimpleServer stop() call
- Qt自定义插件无法加载 - "Shared Library Not Found"
- 是否应将移出对象保留为"safe"状态?
- 在存在分配器重新启动的情况下,使用null_mutex Safe是boost :: fast_pool_allocato