【实例说明】:一个缓存行有 64 字节,一个long占8个字节,而 Java 程序的对象头固定占 8 字节(32位系统)或 12 字节( 64 位系统默认开启压缩, 不开压缩为 16 字节),所以我们只需要填 6个无用的长整型补上6*8=48字节,让不同的 VolatileLong 对象处于不同的缓存行,就避免了伪共享( 64 位系统超过缓存行的 64 字节也无所谓,只要保证不同线程不操作同一缓存行就可以了)。
四、伪共享避免1.缓存行填充(让不同线程操作的对象处于不同的缓存行)
1)缓存行手动填充
2)使用Contended注解自动进行填充
2.使用编译指示,来强制每一个变量对齐(略)
五、总结1)CPU 缓存是以缓存行为单位进行操作的,产生伪共享问题的根源在于不同的CPU核同时操作同一个缓存行;
2)可以通过缓存行填充来解决伪共享问题,且Java8 中引入了@sun.misc.Contended注解来自动填充;
3)一个缓存行有四种状态,分别为:M(修改)E(专有)S(共享)I(无效);
4)每个缓存行所处的状态根据本核和其它核的读写操作在4个状态间进行迁移;
5)不是所有的场景都需要解决伪共享问题,因为CPU缓存是有限的,填充会牺牲掉一部分缓存;
over