在使用Unsafe之前我们需要先实例化它。但我们不能通过像Unsafe unsafe = new Unsafe()这种简单的方式来实现Unsafe的实例化,这是由于Unsafe的构造方法是私有的。Unsafe有一个静态的getUnsafe()方法,但是如果天真的以为调用该方法就可以的话,那你将遇到一个SecurityException异常,这是由于该方法只能在被信任的代码中调用。
We can create classes in runtime, for example from compiled .class file. To perform that read class contents to byte array and pass it properly to defineClass method.
Documentation for park method from Unsafe class contains longest English sentence I’ve ever seen:
Block current thread, returning when a balancing unpark occurs, or a balancing unpark has already occurred, or the thread is interrupted, or, if not absolute and time is not zero, the given time nanoseconds have elapsed, or if absolute, the given deadline in milliseconds since Epoch has passed, or spuriously (i.e., returning for no “reason”). Note: This operation is in the Unsafe class only because unpark is, so it would be strange to place it elsewhere.
//这个方法用于 a 和 b 哈希值相同但是无法比较时,直接根据两个引用的地址进行比较 //这里源码注释也说了,这个树里不要求完全有序,只要插入时使用相同的规则保持平衡即可 staticinttieBreakOrder(Object a, Object b) { int d; if (a == null || b == null || (d = a.getClass().getName(). compareTo(b.getClass().getName())) == 0) d = (System.identityHashCode(a) <= System.identityHashCode(b) ? -1 : 1); return d; }
说伪共享前,先看看Cache Line 在java编程中使用的场景。如果CPU访问的内存数据不在Cache中(一级、二级、三级),这就产生了Cache Line miss问题,此时CPU不得不发出新的加载指令,从内存中获取数据。通过前面对Cache存储层次的理解,我们知道一旦CPU要从内存中访问数据就会产生一个较大的时延,程序性能显著降低,所谓远水救不了近火。为此我们不得不提高Cache命中率,也就是充分发挥局部性原理。
publicclassDataPadding{ long a1,a2,a3,a4,a5,a6,a7,a8;//防止与前一个对象产生伪共享 int value; long modifyTime; long b1,b2,b3,b4,b5,b6,b7,b8;//防止不相关变量伪共享; boolean flag; long c1,c2,c3,c4,c5,c6,c7,c8;// long createTime; char key; long d1,d2,d3,d4,d5,d6,d7,d8;//防止与下一个对象产生伪共享 }
(openjdk\jdk\src\share\classes\java\util\concurrent\ConcurrentHashMap.java line:2506): /* ---------------- Counter support -------------- */
/** * A padded cell for distributing counts. Adapted from LongAdder * and Striped64. See their internal docs for explanation. */ @sun.misc.Contended staticfinalclassCounterCell { volatilelong value; CounterCell(long x) { value = x; } }
(openjdk\jdk\src\share\classes\java\lang\Thread.java line:2023) // The following three initially uninitialized fields are exclusively // managed by class java.util.concurrent.ThreadLocalRandom. These // fields are used to build the high-performance PRNGs in the // concurrent code, and we can not risk accidental false sharing. // Hence, the fields are isolated with @Contended.
/** The current seed for a ThreadLocalRandom */ @sun.misc.Contended("tlr") long threadLocalRandomSeed;
/** Probe hash value; nonzero if threadLocalRandomSeed initialized */ @sun.misc.Contended("tlr") int threadLocalRandomProbe;
/** Secondary seed isolated from public ThreadLocalRandom sequence */ @sun.misc.Contended("tlr") int threadLocalRandomSecondarySeed;
依据JVM对象继承关系中父类属性与子类属性,内存地址连续排列布局,RingBufferPad的protected long p1,p2,p3,p4,p5,p6,p7;作为缓存前置填充,RingBuffer中的protected long p1,p2,p3,p4,p5,p6,p7;作为缓存后置填充。这样任意线程访问RingBuffer时,RingBuffer放在父类RingBufferFields的属性,都是独占一行Cache line不会产生伪共享问题。如图,RingBuffer的操作字段在RingBufferFields中,使用rbf标识: