Java:缓冲行(cache line)的一些问题

发布于 2022-09-06 23:17:28 字数 159 浏览 21 评论 0

对缓冲行我还有些地方不太理解,
1 缓存一致性下缓冲行失效是不是仅针对volatile,如果不是volatile变量应该不会有这种问题吧?
2 具体实践的时候,什么情况下才进行缓冲行填充?所有高并发情况下成员volatile变量频繁写的类都要进行缓冲行填充吗?都要使用disruptor框架?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你又不是我 2022-09-13 23:17:28

准确来说确实不是针对volatile,而是解决了volatile内存可见性带来的false sharing问题的。如果不是volatile这种问题应该不会存在。

具体实践中,也是一般针对基本数据类型的volatile比较合适,因为行缓冲中的cache line的大小一般也就只有64字节而已。

除了disruptor框架,你可以查看hystrix和java8中的Long adder

樱花细雨 2022-09-13 23:17:28

前几天刚看了几篇相关文章,说一下我的理解吧,权作交流,有不对的地方还请指正。

首先说说我对题目中的几个相关重要概念的理解:

  1. 缓存一致性是指的由于CPU缓存的存在导致的并发访问时多个CPU缓存中的数据不一致的问题。
  2. volatile关键字是在java中使用内存屏障来解决缓存一致性问题的方式。
  3. 缓存行是CPU本身优化缓存使用效率的一种机制,也即从内存到CPU缓存的数据操作是以行为单位的,这一行中可能包含多个变量,而由于该机制,结合MESI协议,当并发操作同一行的不同变量的时候就会产生伪共享问题,也即对不同变量的操作却产生了竞争问题有了同步锁,这种不必要的锁当然会影响性能。

然后,针对题主的问题,说说我的看法:

  1. volatile是用于解决缓存一致性问题,因为volatile实际上只是保证了对CPU缓存的操作立即flush到内存,此时的flush依然是以缓存行为单位的,也即你对某缓存行中的单个变量的volatile实际上是应用到了整个缓存行的所有变量,进而会有不同变量的不必要的操作同步,影响性能,此时便需要解决这个问题。
  2. 缓存行填充就是为了解决伪共享产生的性能问题的,实现方式是使用无用变量填充掉特定行多余部分。所以具体实现的时候,我认为一般情况下,为了性能上的考虑,对volatile变量最好还是应用缓存行填充,而高并发写情况下那是毋庸置疑必须进行填充,否则伪共享问题就真的成了他们所说的“性能杀手”了。
  3. 而不在volatile的情况下,缓存行依然存在,只不过若没有涉及到并发写,就不会有伪共享问题,但如果涉及到并发写,又会用volatile来解决缓存一致性问题。所以从这个角度来说,volatile也算是与缓存行填充一一对应。但有一点还是有必要分清楚,缓存行其实并不与volatile直接关联,而是与同一缓存行中不同变量的并发写直接关联,volatile是解决并发写,缓存行填充是解决并发写时flush缓存行产生的伪共享性能问题。

最后总结一下题主两个问题的答案:

  1. 缓存一致性是一个需要解决的问题,volatile缓存行填充是解决两个不同但有一定关联关系的问题的方式,如果没有并发写,也就没有缓存一致性问题,也就不需要volatile和缓存行填充了
  2. 缓存行填充是为了解决伪共享问题,理论上来说,所有并发写入同一缓存行的不同变量的操作都会产生伪共享问题,高并发下volatile变量频繁写肯定需要进行缓存行填充。至于disruptor框架,不巧我还不是很了解,但如果你能手动进行缓存行填充的话,也不是必须要用吧?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文