在this video关于Disruptor的并发框架中,提到了Java的Atomic *类(例如AtomicLong)的lazySet方法。根据{{3}},此方法“最终设置为给定值”。
有没有人知道实现这个的底层机制是什么(特别是在Windows上的x86,如果这是相关的)。它不能是documentation,因为这会设置值并确保在返回之前刷新缓存行,如果我没弄错的话。
答案 0 :(得分:4)
这基本上调用unsafe.putOrderedLong()
这是一个本机函数。基于 ordered (lazy)vs volatile (立即)之间的不安全区别。我几乎确定(懒惰)版本只是解析为storestore
,而volatile需要更昂贵的loadstore
。这样可以保留线程语义(对于设置线程)而不会停止所有其他核心。最终读者将获得新的价值。
[编辑:那说(这是推测性的),我某些懒惰商店使用完全易失性使用的“更轻”内存防护 - 如果平台提供它。例如。我没有看到你在C#中不能做同样的事情,比如x86]
这种类似的东西的典型用法是计数器(比如队列深度)。如果你在每次迭代时遇到一个volatile,它将不会是“高性能”,因为你在每次迭代中都会产生缓存一致性的全部成本。如果你的并发交互允许'模糊'读数然后你的(通过内存交互)那么这种技术降低了维护整个系统状态的成本(在可接受的误差范围内,例如你的队列深度读数有点偏。)
[p.s./edit:discussion of fencing by Distruptor's designers。]
答案 1 :(得分:2)
在Bug 6275329中找到了对此实现的描述:
语义是保证写入不会被任何重新排序 上一次写入,但可以与后续操作重新排序 (或等效地,可能不会被其他线程看到)直到 发生一些其他易失性写入或同步动作。)
...
对于那些喜欢用这些操作来思考这些操作的人 常见的多处理器上的机器级障碍,lazySet提供了一个 在商店门槛之前(这是一种无操作或非常便宜的 在当前平台上),但没有商店负载障碍(通常是 挥发性写的昂贵部分)