笔记 · Cache line 缓存行对齐
假设 计算单元 要找变量X,需要从最近的缓存中找L1 --> L2 --> L3 --> 主内存。 如果是要读取一个变量则顺序为:主内存 -> L3 -> L2 -> L1,之后 计算单元 开始计算。
当我们读一个数据,会把相关的数据一块读过来(即 按块读取),
class B { private static class T { public volatile long x = 0L; // long 类型 8字节 } public static T[] arr = new T[2]; static { arr[0] = new T(); arr[1] = new T(); } /** * 在内存中有2块数据arr[0].x 记为x、arr[1].x 记为y,它们在同一个缓存行中。 * 在CPU层面的数据一致性,是以cache line为单位(64字节)的。所以当同一个缓存 * 行中的某个值发生了变化(volatile保证可见性),需要通知另一个线程去拉取最新值。 **/ public static void main(String[] args) { Thread t1 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++){ // 线程t1 修改x的之后,每次都会通知线程t2拉取最新值 arr[0].x = i; } }); Thread t2 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++){ arr[1].x = i; } }); final long start = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println((System.nanoTime() - start) / 100_0000); } }
优化
class B1 { private static class Padding { // long 类型 8字节 共占用56个字节 public volatile long p1,p2,p3,p4,p5,p6,p7; } private static class T extends Padding { // 56 + 8 = 64 public volatile long x = 0L; } public static T[] arr = new T[2]; static { arr[0] = new T(); arr[1] = new T(); } public static void main(String[] args) { Thread t1 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++){ // 线程t1 的x变量,与线程t2 的x变量不在同一个 缓存行中,所以每次修改都不用通知 // t2,这样就提高了效率。 arr[0].x = i; } }); Thread t2 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++){ arr[1].x = i; } }); final long start = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println((System.nanoTime() - start) / 100_0000); } }
上一篇:
通过多线程提高代码的执行效率例子