混合原子和非原子变量和缓存

Posted

技术标签:

【中文标题】混合原子和非原子变量和缓存【英文标题】:mix atomic and non atomic variables and caches 【发布时间】:2017-08-15 08:50:23 【问题描述】:

假设我们有这段代码是正确的(至少我希望如此):

std::atomic<int> a;
std::atomic<bool> readyfalse;
void threadA() 
    a.store(666, std::memory_order_relaxed);
    ready.store(true, std::memory_order_release);


void threadB() 
    while(!ready.load(std::memory_order_acquire));
    process(a.load(std::memory_order_relaxed));

我的问题是:如果您使用的是int a; 而不是std::atomic&lt;int&gt; a;,它也正确吗?还是缓存刷新/失效的问题?

【问题讨论】:

如果你不得不问...使用顺序一致性。除非大量注释和封装,否则即使您了解自己在做什么,维护您的代码的人也不会。 它并不是针对特定用例的。它更多的是理论而不是其他东西;)。但是,此代码是否可以在顺序一致性下工作? 对我来说看起来不错。我鼓励你观看名为“原子武器”的讲座。在那之后,这一切对我来说都是有意义的。 youtube.com/watch?v=c1gO9aB9nbs 经典的“完整”模式,其中原子ready 变量扮演一个标志的角色,它保护其他变量的设置。受此机制保护的变量不必是原子的。 (也就是说,是的,你可以使用int a;)。 【参考方案1】:

无论这是否是一个好主意,例如,您的代码很好..

您可以将 a 的原子类型替换为常规的 int(或任何类型)。 C++ 标准使用以下短语(第 1.10.1-6 节)支持您的情况:

某些库调用与另一个线程执行的其他库调用同步。例如,原子存储释放与从存储中获取其值的加载获取同步

由于threadB 加载了threadA 存储的ready 的值(它在循环中等待它),synchronizes-with 关系就建立了。 因此,a.load() 观察到了a.store() 的记忆效应。另一种说法是 a.store() happen-before a.load()

【讨论】:

是的,但我的问题更多的是:用非原子变量替换原子变量是否正确。你在一开始就回答了;)

以上是关于混合原子和非原子变量和缓存的主要内容,如果未能解决你的问题,请参考以下文章

java并发编程原子变量和非阻塞的同步机制

Java并发编程实战 第15章 原子变量和非阻塞同步机制

第十五章 原子变量和非阻塞同步机制

并发编程,高速缓存,原子操作,指令重排序

并发编程,高速缓存,原子操作,指令重排序

同步互斥阻塞