java.lang.Thread中新增的字段是什么?
在Java 8中,java.lang.Thread中新增的字段是什么?,java,java-8,thread-local,Java,Java 8,Thread Local,在Java 8中,Java.lang.Threadclass获得了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 threa
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中所说,它是由类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
?内部?这些是内部字段。解释只能来自JDK开发人员自己。我从Doug Lea(日期为2013年1月)那里找到了一个关于这一点的文章,解释了这些字段背后的原理,以及它们为什么在线程类中
当我们引入ThreadLocalRandom
时,我们保守地
将其实现为使用实际的ThreadLocal
。然而,
随着它的应用越来越广泛,它值得改进
通过housingThreadLocalRandom
状态实现
(和相关簿记)在类线程中
本身。
这将需要三个字段(总共16个字节)
因此,我建议在类线程中添加以下内容:
// 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;
这样做的原因是:
统一更快地访问ThreadLocalRandom
状态。虽然
ThreadLocal
访问通常已经相当快了,这是
不仅速度更快,而且在用户
程序创建大量的ThreadLocal
s
可能(可能)导致任何给定的访问成为
慢一点
使用ThreadLocalRandom
的任何程序的总占用空间都更小。
三个字段所需的空间比装入填充字段所需的空间小
ThreadLocal
对象。随着ThreadLocalRandom
的广泛使用
在JDK本身中,这包括几乎所有的程序
java.util.concurrent ForkJoinPool
进一步节省时间/空间,
ConcurrentHashMap
,LongAdder
,ConcurrentSkipList
,以及其他
可以使用这种形式的统一ThreadLocalRandom
记账而不是自己的专用ThreadLocal
s
就像他们现在做的那样
我将通过添加一个小的答案来复活这个问题,因为我刚刚在LongAdder中找到了这个问题,有一个很棒的视频,Shipilev用简单的话解释了这一点(它是俄语的),下面是链接:
对于ForkJoinPool的情况,它需要将任务放入队列并从队列中移除,通过良好的解决方案来解决该队列
该prng必须非常快速且高度可扩展。好的,java有一个现成的:ThreadLocalRandom。为了将这些字段放入ThreadLocalRandom,它需要一个ThreadLocal,而ThreadLocal又在内部使用ThreadLocalMap(想想HashMap)
ThreadLocal.get(想想HashMap#get)比直接从线程获取这些字段要慢得多。不知道这一点-我本来会/实际上已经对你之前关于“tlr”
@luk2302的问题有了答案非常感谢你,但是有人否决了我的问题,所以我不得不删除它。对此我真的很抱歉。否决票不是删除问题或答案的理由,例如,我给了你一个向上的投票,使其为0分。非常感谢你的纸质链接,+1。但是这个解决方案看起来有点混乱,你不这么认为吗?另外,我也不太明白,为什么这些字段不能放在ThreadLocalRandom
类中?@Andremoniy老实说,我无法判断JDK开发人员自己提出的技术解决方案。将它们添加到线程中的原因可能归结为Doug Lea的评论:“但主要是:用于“永久”的空间“线程局部变量需要放在某个地方;为什么不选择物流问题最少的地方呢?请注意,类java.lang.Thread只是系统上每个线程存储的冰山一角。因此,添加16个字节几乎是不可检测的。”@Andremoniy:如果这些字段是在ThreadLocalRandom
中声明的,那么每个线程都需要一个不同的ThreadLocalRandom
实例,这需要ThreadLocalRandom.current()
使用ThreadLocal
变量,该变量被认为效率不够。因此,ThreadLocalRandom.current()
返回一个单例实例,这很便宜,但意味着它不能承载每个线程必须不同的字段。因此,在给定当前实现的情况下,这些字段存储在线程
实例中。