程序设计的5个底层逻辑,决定你能走多快
当然内存对齐另外一个原因是为了让字段只出现在同一个 CPU 的缓存行中,如果字段不对齐,就有可能出现一个字段的一部分在缓存行 1 中,而剩下的一半在 缓存行 2 中,这样该字段的读取需要替换两个缓存行,而字段的写入会导致两个缓存行上缓存的其他数据都无效,这样会影响程序性能。 通过内存对齐可以避免一个字段同时存在两个缓存行里的情况,但还是无法完全规避缓存伪共享的问题,也就是一个缓存行中存了多个变量,而这几个变量在多核 CPU 并行的时候,会导致竞争缓存行的写权限,当其中一个 CPU 写入数据后,这个字段对应的缓存行将失效,导致这个缓存行的其他字段也失效。 在 Disruptor 中,通过填充几个无意义的字段,让对象的大小刚好在 64 字节,一个缓存行的大小为64字节,这样这个缓存行就只会给这一个变量使用,从而避免缓存行伪共享,但是在 jdk7 中,由于无效字段被清除导致该方法失效,只能通过继承父类字段来避免填充字段被优化,而 jdk8 提供了注解@Contended 来标示这个变量或对象将独享一个缓存行,使用这个注解必须在 JVM 启动的时候加上 -XX:-RestrictContended 参数,其实也是用空间换取时间。 jdk6 --- 32 位系统下 public final static class VolatileLong { public volatile long value = 0L; public long p1, p2, p3, p4, p5, p6; // 填充字段 }
jdk7 通过继承
public class VolatileLongPadding { public volatile long p1, p2, p3, p4, p5, p6; // 填充字段 } public class VolatileLong extends VolatileLongPadding { public volatile long value = 0L; }
jdk8 通过注解
@Contended public class VolatileLong { public volatile long value = 0L; } NPTL和 Java 的线程模型 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |