我问自己,一个原子bool ready标志是否可以确保数据在线程之间同步(我已经阅读了这个Synchronization Mechanism For "data ready" Flag?)但是没有评论回答我的问题。
例如,请参阅此代码:
#include<atomic>
#include<thread>
class BIG_DATA {
public:
BIG_DATA(){ std::this_thread::sleep_for(std::chrono::seconds(1)); }//some big data to init ......
};
void init_BIG_DATA(BIG_DATA* & location, std::atomic<bool>& flag ) {
if (flag.load())throw("error : data already loaded");
location = new BIG_DATA(); //heavy operation
flag.store(true);
}
class data {
public:
data() {
ready.store(false);
std::thread t = std::thread(init_BIG_DATA,std::ref(_data),std::ref(ready));
t.detach();
}
BIG_DATA* get_data() {
if (ready.load()) return _data;
else return nullptr;
}
private:
BIG_DATA* _data = nullptr;
std::atomic<bool> ready;
};
如果我有这样的主要内容,请在此代码中:
data d;
while (d.get_data() == nullptr) ; // wait for Big data to be constructed in an other thread
BIG_DATA* BD = d.get_data();
// do somethin with big data
我是否确保我对BIG_DATA *(BD)所做的事情是正确的,并且该对象是在创建者和工作者线程之间进行了对比的? 这段代码是否安全?
答案 0 :(得分:0)
这里存在设计问题。看一下代码,我看到了两个要求:
必须初始化BIG_DATA,这需要一些时间。
在构建BIG_DATA时,主线程必须阻塞。
这引出了一个问题,因为BIG_DATA的构造仅在一个线程中进行,为什么不在主线程中简单地创建呢?
在这种情况下,与变量更改的时间同步和跨线程传播有关的所有问题都会消失。
但是,除此之外,是的,这段代码是线程安全的,因为原子的默认内存顺序是“完全顺序一致性”。这意味着对BIG_DATA指针的写入将“发生在对保护它的原子的写入之前”,并且该顺序将在线程之间传播。
具有此内存顺序的存储操作会执行释放操作:在此存储之后,不能对当前线程中的内存访问进行重新排序。这可以确保当前线程中的所有写入在获取相同原子变量的其他线程中可见,并且带有依赖关系到原子变量的写入在消耗相同原子的其他线程中变得可见。