Improving ThreadLocalRandom (and related classes)

Aleksey Shipilev aleksey.shipilev at oracle.com
Wed Jan 9 10:55:09 UTC 2013


On 01/08/2013 08:33 PM, Doug Lea wrote:
> However, the actual ThreadLocalRandom object is padded to avoid 
> memory contention (which wouldn't be necessary or useful if already
> embedded withing Thread).

I'm tempted to disagree. While it is true most of the callers are
accessing Thread in the context of currentThread(), and most of the
Thread state is not updated, it can catastrophically break down once we
cram in the heavily updated fields.

E.g. this is the java.lang.Thread field layout as of 7u12:

$ java -jar java-object-layout.jar java.lang.Thread
Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.

java.lang.Thread
 offset  size                     type description
      0    12                          (assumed to be the object header
+ first field alignment)
     12     4                      int Thread.priority
     16     8                     long Thread.eetop
     24     8                     long Thread.stackSize
     32     8                     long Thread.nativeParkEventPointer
     40     8                     long Thread.tid
     48     4                      int Thread.threadStatus
     52     1                  boolean Thread.single_step
     53     1                  boolean Thread.daemon
     54     1                  boolean Thread.stillborn
     55     1                          (alignment/padding gap)
     56     4                   char[] Thread.name
     60     4                   Thread Thread.threadQ
     64     4                 Runnable Thread.target
     68     4              ThreadGroup Thread.group
     72     4              ClassLoader Thread.contextClassLoader
     76     4     AccessControlContext Thread.inheritedAccessControlContext
     80     4           ThreadLocalMap Thread.threadLocals
     84     4           ThreadLocalMap Thread.inheritableThreadLocals
     88     4                   Object Thread.parkBlocker
     92     4            Interruptible Thread.blocker
     96     4                   Object Thread.blockerLock
    100     4 UncaughtExceptionHandler Thread.uncaughtExceptionHandler
    104                                (object boundary, size estimate)

That means adding a few primitive fields can easily overlap with the
fields for another Thread and make the false sharing quite the issue.
Padding out the inlined TLR state would save us from this trouble
(thankfully, @Contended can make that without the magical field
arrangements and finger crossing).

We can @Contended the whole Thread, which means pushing Thread to
consume 256 bytes instead of 104+ as it is now. While this seems to be
the large increase, it is a global win since padded TLR state is gone,
and we effectively hiding the Thread state in the "padding shadow".

My 2c.

-Aleksey.



More information about the core-libs-dev mailing list