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

时间:2015-12-30 12:01:46

标签: java java-8 thread-local

在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类中也可以满足相同的代码段。)

然后在几个java.concurrent位置内部使用此偏移量。

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

2 个答案:

答案 0 :(得分:6)

这些是内部字段。解释只能来自JDK开发人员自己。我从2013年1月的Doug Lea那里找到了post,这解释了这些字段背后的基本原理以及它们为什么都在Thread课程内。

  

当我们介绍ThreadLocalRandom时,我们保守地说   实现它以使用实际的ThreadLocal。然而,   随着它被广泛使用,它值得改进   住房ThreadLocalRandom州的实施   课程Thread本身(和相关的簿记)。   这将需要三个字段(总共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 s   可能(概率上)导致任何给定的访问变为   慢。

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

  4.   
  5. java.util.concurrent ForkJoinPool进一步节省时间/空间,   ConcurrentHashMapLongAdderConcurrentSkipList等   可以使用统一ThreadLocalRandom的这种形式的类   簿记而不是他们自己的专用ThreadLocal   正如他们现在所做的那样。

  6.   

答案 1 :(得分:1)

我也会通过添加一个小答案来复活这个,因为我只是在LongAdder中点击了这个,并且有一个很棒的视频,Shipilev用简单的词语解释了这个(俄语),这里是链接:ThreadLocalRandom

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

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

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