@sun.misc.Contended避免伪共享(false sharing)

来源:互联网 发布:php $a=array_pop 编辑:程序博客网 时间:2024/06/16 21:51
转载自:http://www.myexception.cn/program/1630142.html

       Java8中使用sun.misc.Contended注解来避免伪共享(false sharing)。关于伪共享这个概念,可以先参照http://ifeve.com/falsesharing/

       伪共享的例子:
[java] view plain copy
  1. public class VolatileLong {  
  2.     volatile long v = 0L;  
  3. }  
       如果有两个VolatileLong对象,会被load到同一个缓存行里面,如果一个线程要修改对象1,另一个线程同时要修改对象2,此时就要面对伪共享问题(core1对缓存行中对象1的修改,导致core2中同一缓存行失效,即缓存的对象2需要重新load)。

       jdk6中的解决办法:
[java] view plain copy
  1. public class VolatileLong {  
  2.     volatile long p0, p1, p2, p3, p4, p5, p6;  
  3.     volatile long v = 0L;  
  4.     volatile long q0, q1, q2, q3, q4, q5, q6;  
  5. }  
       上面的方式也就是long padding来避免伪共享,使用无关数据来填充缓存行,使得两个VolatileLong对象不会load到同一个缓存行里面。无锁并发框架Disruptor正是采用的这种方式。

       long padding的解决办法不怎么优雅,并且在jdk7某个版本以后能会优化掉long padding,详细参考http://ifeve.com/false-sharing-java-7/。但是java8已经给出了官方的解决办法,就是sun.misc.Contended注解。
[java] view plain copy
  1. // jdk8新特性,Contended注解避免false sharing  
  2. // Restricted on user classpath  
  3. // Unlock: -XX:-RestrictContended  
  4. @sun.misc.Contended  
  5. public class VolatileLong {  
  6.     volatile long v = 0L;  
  7. }  
       这里,JVM就不会将被Contended注解的两个VolatileLong对象load到同一个缓存行里面。要注意的是user classpath使用此注解默认是无效的,需要在jvm启动时设置-XX:-RestrictContended。(不太理解。。。经测试,自己应用程序的sun.misc.Contended注解的类需要-XX:-RestrictContended才能生效,是不是对jdk源码中的sun.misc.Contended不需要上述注解就可以生效了?)
       jdk8中有很多地方已经使用了sun.misc.Contended:
       java/util/concurrent/ConcurrentHashMap.java
[java] view plain copy
  1. /** 
  2.  * A padded cell for distributing counts.  Adapted from LongAdder 
  3.  * and Striped64.  See their internal docs for explanation. 
  4.  */  
  5. @sun.misc.Contended static final class CounterCell {  
  6.     volatile long value;  
  7.     CounterCell(long x) { value = x; }  
  8. }  
       java/util/concurrent/Exchanger.java
[java] view plain copy
  1. /** 
  2.  * Nodes hold partially exchanged data, plus other per-thread 
  3.  * bookkeeping. Padded via @sun.misc.Contended to reduce memory 
  4.  * contention. 
  5.  */  
  6. @sun.misc.Contended static final class Node {  
  7.     int index;              // Arena index  
  8.     int bound;              // Last recorded value of Exchanger.bound  
  9.     int collides;           // Number of CAS failures at current bound  
  10.     int hash;               // Pseudo-random for spins  
  11.     Object item;            // This thread's current item  
  12.     volatile Object match;  // Item provided by releasing thread  
  13.     volatile Thread parked; // Set to this thread when parked, else null  
  14. }  
原创粉丝点击