原子布尔标志可以确保同步吗?
Posted
技术标签:
【中文标题】原子布尔标志可以确保同步吗?【英文标题】:Can An Atomic Bool Flag Ensure Synchronization? 【发布时间】:2016-06-25 12:20:23 【问题描述】:我在问自己,原子 bool 就绪标志是否可以确保数据在线程之间同步(我已经阅读过这个 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) 所做的事情是正确的,并且该对象在创建者和工作线程之间被同步化? 这段代码线程安全吗?
【问题讨论】:
使用mutex
函数,当你的资源在thread
中使用时,你可以在此之前锁定mutex
变量,完成线程工作后解锁互斥锁。
我知道,但我很好奇是否有无锁方法可以做到这一点?如果这行得通?
它实际上是用于 sdl 应用程序的图像加载器,我在其中从磁盘或互联网等加载图像
注意:不要使用分离,除非你知道自己在做什么:***.com/questions/22803600/…
这是一种幼稚的同步方法。如果两个函数同时调用 init 函数,它将不起作用,所以不。它不是线程安全的。
【参考方案1】:
这里存在设计问题。查看代码,我看到两个要求:
必须初始化 BIG_DATA,这需要一些时间。
在构造 BIG_DATA 时主线程必须阻塞。
这引出了一个问题,既然 BIG_DATA 的构造只发生在一个线程中,为什么不简单地在主线程中创建它呢?
在这种情况下,与时间同步和变量更改的跨线程传播有关的所有问题都将消失。
但是,除此之外,是的,这段代码是线程安全的,因为原子的默认内存顺序是“完全顺序一致性”。这意味着对 BIG_DATA 指针的写入将在写入保护它的原子之前“发生”,并且该排序将跨线程传播。
具有此内存顺序的存储操作执行释放操作:当前线程中的任何内存访问都不能在此存储之后重新排序。这确保了当前线程中的所有写入在获取相同原子变量的其他线程中都是可见的,并且将依赖项携带到原子变量中的写入在使用相同原子的其他线程中变得可见。
【讨论】:
所以事情是我想用它从磁盘或互联网或其他地方加载图像所以我想要的是:-image 一旦准备好就使用,但只要它不是'我不显示它(只要抛出 nullptr),而是显示另一个元素。我的方法好吗? 解决这个问题的正常方法是,加载图像的线程会将对闭包的调用发布到在主线程中运行的消息队列中。此调用将通知主线程图像已准备好。以上是关于原子布尔标志可以确保同步吗?的主要内容,如果未能解决你的问题,请参考以下文章