Java填充性能破坏

ura*_*rag 2 java performance multithreading false-sharing

嗨,大家好,所以我得到了这段代码

public class Padding {

  static class Pair {

        volatile long c1;
        // UN-comment this line and see how perofmance is boosted * 2
      //  long q1; //Magic dodo thingy

        volatile long c2;

  }

  static Pair p = new Pair();

  static class Worker implements Runnable {

        private static final int INT = Integer.MAX_VALUE/8;
        private boolean b;
        Worker(boolean b) {
              this.b = b;
        }

        public void run() {
              long start = System.currentTimeMillis();
              if (b) {
                    for (int i = 0; i < INT; i++) {
                          p.c1++;
                          res += Math.random();
                    }
              } else {
                    for (int i = 0; i < INT; i++) {
                          p.c2++;
                          res += Math.random();
                    }
              }
              long end = System.currentTimeMillis();
              System.out.println("took: " + (end-start) + " Result:" + p.c1+p.c2);
        }

  }


  public static void main(String[] args) {
        System.out.println("Starting....");
        Thread t1 = new Thread(new Worker(true));
        Thread t2 = new Thread(new Worker(false));

        t1.start();
        t2.start();


  }
Run Code Online (Sandbox Code Playgroud)

}

因此,如果我运行它需要大约11秒,但如果我取消注释qa1它运行3秒.我试图在互联网上找到一些东西,但没有提供足够的信息.据我所知,它与JVM优化有关,而长q1可能使内存(或缓存)分配有些好.我的问题是什么,有人知道我在哪里可以阅读更多.谢谢

Coo*_*tri 8

虚假共享会降低您的示例中的性能- c1并且c2实例被放置在同一缓存行中,并且线程需要在每个不同字段的增量处向/从主存储器刷新/加载值,以在突变缓存行复制失效后保持缓存一致性.

在你的情况下,它足以声明一个多q1之后长字段c1做出c2去到另一个高速缓存行(大小只有64 bytesx86家庭).在高速缓存管理变得更有效之后 - 线程可以使用不同的高速缓存行,并且不会使另一个线程的高速缓存行的副本无效.

有许多文章专门讨论这个问题的硬件性质(以及避免它的软件方法).通过"足迹填充"解决方案(与您的一样)处理错误共享长期以来一直很棘手 - Java平台保证字段顺序和运行时缓存行填充将完全按照您在类声明中的预期.即使是"次要"平台更新或切换到另一个VM实现也可以制动解决方案(因为字段 - 尤其是未使用的虚拟变量 - 是优化的主题).

这是whу JEP-142被引入和@Contended注释被实施Java 8.此批注允许您配置应将类的哪些字段放在不同的缓存行上.但是现在它只是一个虚拟机提示,没有任何关于在所有情况下避免错误共享的绝对保证,所以你应该仔细查看你的代码并验证它的行为(当然,如果你的应用程序对错误的共享问题很敏感)