java.lang.Thread中的新增附加字段,有什么想法?

在Java 8中, java.lang.Thread类有3个新字段:

 /** 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; 

正如它在Javadoc中所说的那样,它是由java.util.concurrent.ThreadLocalRandom类专门管理的。

此外,在ThreadLocalRandom它们以非常奇怪的方式使用:

 SEED = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSeed")); PROBE = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomProbe")); SECONDARY = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSecondarySeed")); 

(在LockSupport类中也LockSupport相同的代码段)。

然后这个偏移在内部用于几个java.concurrent地方。

这个想法是什么? 为什么这些字段是java.lang.Thread ? 为什么不在ThreadLocalRandom

这些是内部字段。 解释只能来自JDK开发人员自己。 我能够从2013年1月的Doug Lea找到一篇关于这个的post ,它解释了这些领域背后的基本原理以及它们在Thread类中的原因。

当我们介绍ThreadLocalRandom ,我们保守地实现它以使用实际的ThreadLocal 。 但是,随着它的使用越来越广泛,通过在Thread类本身中容纳ThreadLocalRandom状态(和相关的簿记)来改进实现是值得的。 这将需要三个字段(总共16个字节)。

所以我建议在Thread类中添加以下内容:

 // The following three initially uninitialized fields are exclusively // managed by class java.util.concurrent.ThreadLocalRandom. /** The current seed for a ThreadLocalRandom */ long threadLocalRandomSeed; /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ int threadLocalRandomProbe; /** Secondary seed isolated from public ThreadLocalRandom sequence */ int threadLocalRandomSecondarySeed; 

这样做的原因是:

  1. ThreadLocalRandom状态的访问速度更快。 虽然ThreadLocal访问通常非常快,但这不仅更快,在用户程序创建大量ThreadLocal的情况下也不会降低,这可能(概率上)导致任何给定访问变慢。

  2. 使用ThreadLocalRandom任何程序的总占用空间更小。 三个字段比装入填充的ThreadLocal对象所需的空间更少。 随着ThreadLocalRandom在JDK中的广泛使用,这几乎包括所有程序。

  3. java.util.concurrent ForkJoinPoolConcurrentHashMapLongAdderConcurrentSkipList以及其他类可以使用这种forms的统一ThreadLocalRandom簿记而不是他们现在所使用的专用ThreadLocal进一步节省时间/空间。

我将通过添加一个小答案来复活这个,因为我刚刚在LongAdder中看到这个,并且有一个很棒的video,Shipilev用简单的词语解释了这个(俄语),这里是链接: ThreadLocalRandom

对于ForkJoinPool的情况,它需要将任务放入队列并从队列中删除,该队列exaclty通过良好的PRNG解决。

这个程序必须非常快速和高度可扩展。 好吧,java有一个到位:ThreadLocalRandom。 要将这些字段放入ThreadLocalRandom,它需要一个ThreadLocal,而ThreadLocal又在内部使用ThreadLocalMap(想想HashMap)。

ThreadLocal.get(想想HashMap#get)比直接从Thread获取这些字段要慢得多。