java.lang.Thread 中的新附加字段,这是什么想法?
New additional fields in java.lang.Thread, what is the idea?
在Java8中,java.lang.Thread
class得到了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 中所述,由 class java.util.concurrent.ThreadLocalRandom
.
独家管理
此外,在 ThreadLocalRandom
中,它们的使用方式非常怪异:
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
(在LockSupport
class中也可以遇到相同的代码段)。
然后这个偏移量在几个 java.concurrent
地方内部使用。
这是什么想法?为什么这些字段位于 java.lang.Thread
内?为什么不在 ThreadLocalRandom
内?
这些是内部字段。解释只能来自 JDK 开发人员自己。我从 2013 年 1 月的 Doug Lea 那里找到了关于此的 post,它解释了这些字段背后的基本原理以及为什么它们在 Thread
class.
中
When we introduced ThreadLocalRandom
, we conservatively
implemented it to use an actual ThreadLocal
. However,
as it becomes more widely used, it is worth improving
the implementation by housing ThreadLocalRandom
state
(and related bookkeeping) in class Thread
itself.
This would entail three fields (16 total bytes).
So I propose adding the following to class 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;
The reasons for doing it in this way are:
Uniformly faster access to ThreadLocalRandom
state. While
ThreadLocal
access is normally pretty fast already, this is
not only faster, it does not degrade in cases where user
programs create large numbers of ThreadLocal
s, which
may (probabilistically) cause any given access to become
slower.
Smaller total footprint for any program using ThreadLocalRandom
.
Three fields require less space than boxing into a padded
ThreadLocal
object. As ThreadLocalRandom
becomes widely used
within JDK itself, this includes just about all programs.
Further time/space savings for java.util.concurrent ForkJoinPool
,
ConcurrentHashMap
, LongAdder
, ConcurrentSkipList
, and other
classes that could use this form of the unified ThreadLocalRandom
bookkeeping rather than their own special-purpose ThreadLocal
s
as they now do.
我也会通过添加一个小答案来复活这个问题,因为我刚刚在 LongAdder 中点击了这个并且有一个很棒的视频,其中 Shipilev 用简单的语言解释了这个(它是俄语),这里是 link: ThreadLocalRandom
对于ForkJoinPool的情况,它需要将任务放入队列和从队列中移除,这个队列的问题通过一个很好的解决PRNG。
此 prng 必须非常快速且高度可扩展。嗯,java 有一个:ThreadLocalRandom。为了将这些字段放入 ThreadLocalRandom,它需要一个 ThreadLocal,而 ThreadLocal 又在内部使用了一个 ThreadLocalMap(想想 HashMap)。
ThreadLocal.get(想想 HashMap#get)比直接从 Thread 获取这些字段要慢得多。
在Java8中,java.lang.Thread
class得到了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 中所述,由 class java.util.concurrent.ThreadLocalRandom
.
此外,在 ThreadLocalRandom
中,它们的使用方式非常怪异:
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
(在LockSupport
class中也可以遇到相同的代码段)。
然后这个偏移量在几个 java.concurrent
地方内部使用。
这是什么想法?为什么这些字段位于 java.lang.Thread
内?为什么不在 ThreadLocalRandom
内?
这些是内部字段。解释只能来自 JDK 开发人员自己。我从 2013 年 1 月的 Doug Lea 那里找到了关于此的 post,它解释了这些字段背后的基本原理以及为什么它们在 Thread
class.
When we introduced
ThreadLocalRandom
, we conservatively implemented it to use an actualThreadLocal
. However, as it becomes more widely used, it is worth improving the implementation by housingThreadLocalRandom
state (and related bookkeeping) in classThread
itself. This would entail three fields (16 total bytes).So I propose adding the following to class 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;
The reasons for doing it in this way are:
Uniformly faster access to
ThreadLocalRandom
state. WhileThreadLocal
access is normally pretty fast already, this is not only faster, it does not degrade in cases where user programs create large numbers ofThreadLocal
s, which may (probabilistically) cause any given access to become slower.Smaller total footprint for any program using
ThreadLocalRandom
. Three fields require less space than boxing into a paddedThreadLocal
object. AsThreadLocalRandom
becomes widely used within JDK itself, this includes just about all programs.Further time/space savings for
java.util.concurrent ForkJoinPool
,ConcurrentHashMap
,LongAdder
,ConcurrentSkipList
, and other classes that could use this form of the unifiedThreadLocalRandom
bookkeeping rather than their own special-purposeThreadLocal
s as they now do.
我也会通过添加一个小答案来复活这个问题,因为我刚刚在 LongAdder 中点击了这个并且有一个很棒的视频,其中 Shipilev 用简单的语言解释了这个(它是俄语),这里是 link: ThreadLocalRandom
对于ForkJoinPool的情况,它需要将任务放入队列和从队列中移除,这个队列的问题通过一个很好的解决PRNG。
此 prng 必须非常快速且高度可扩展。嗯,java 有一个:ThreadLocalRandom。为了将这些字段放入 ThreadLocalRandom,它需要一个 ThreadLocal,而 ThreadLocal 又在内部使用了一个 ThreadLocalMap(想想 HashMap)。
ThreadLocal.get(想想 HashMap#get)比直接从 Thread 获取这些字段要慢得多。