jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
changeset 43219 566b551b7820
parent 42322 c3474fef4fe4
child 43226 6fc9bdd300f1
equal deleted inserted replaced
43218:8be65fea76fc 43219:566b551b7820
    34  */
    34  */
    35 
    35 
    36 package java.util.concurrent;
    36 package java.util.concurrent;
    37 
    37 
    38 import java.io.ObjectStreamField;
    38 import java.io.ObjectStreamField;
       
    39 import java.lang.invoke.MethodHandles;
       
    40 import java.lang.invoke.VarHandle;
    39 import java.security.AccessControlContext;
    41 import java.security.AccessControlContext;
    40 import java.util.Random;
    42 import java.util.Random;
    41 import java.util.Spliterator;
    43 import java.util.Spliterator;
    42 import java.util.concurrent.atomic.AtomicInteger;
    44 import java.util.concurrent.atomic.AtomicInteger;
    43 import java.util.concurrent.atomic.AtomicLong;
    45 import java.util.concurrent.atomic.AtomicLong;
    46 import java.util.function.LongConsumer;
    48 import java.util.function.LongConsumer;
    47 import java.util.stream.DoubleStream;
    49 import java.util.stream.DoubleStream;
    48 import java.util.stream.IntStream;
    50 import java.util.stream.IntStream;
    49 import java.util.stream.LongStream;
    51 import java.util.stream.LongStream;
    50 import java.util.stream.StreamSupport;
    52 import java.util.stream.StreamSupport;
    51 import jdk.internal.misc.Unsafe;
       
    52 
    53 
    53 /**
    54 /**
    54  * A random number generator isolated to the current thread.  Like the
    55  * A random number generator isolated to the current thread.  Like the
    55  * global {@link java.util.Random} generator used by the {@link
    56  * global {@link java.util.Random} generator used by the {@link
    56  * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
    57  * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
   106      * internal documentation for explanations, which are not repeated
   107      * internal documentation for explanations, which are not repeated
   107      * here.)  Because ThreadLocalRandoms are not splittable
   108      * here.)  Because ThreadLocalRandoms are not splittable
   108      * though, we use only a single 64bit gamma.
   109      * though, we use only a single 64bit gamma.
   109      *
   110      *
   110      * Because this class is in a different package than class Thread,
   111      * Because this class is in a different package than class Thread,
   111      * field access methods use Unsafe to bypass access control rules.
   112      * field access methods use VarHandles to bypass access control rules.
   112      * To conform to the requirements of the Random superclass
   113      * To conform to the requirements of the Random superclass
   113      * constructor, the common static ThreadLocalRandom maintains an
   114      * constructor, the common static ThreadLocalRandom maintains an
   114      * "initialized" field for the sake of rejecting user calls to
   115      * "initialized" field for the sake of rejecting user calls to
   115      * setSeed while still allowing a call from constructor.  Note
   116      * setSeed while still allowing a call from constructor.  Note
   116      * that serialization is completely unnecessary because there is
   117      * that serialization is completely unnecessary because there is
   161     static final void localInit() {
   162     static final void localInit() {
   162         int p = probeGenerator.addAndGet(PROBE_INCREMENT);
   163         int p = probeGenerator.addAndGet(PROBE_INCREMENT);
   163         int probe = (p == 0) ? 1 : p; // skip 0
   164         int probe = (p == 0) ? 1 : p; // skip 0
   164         long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
   165         long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
   165         Thread t = Thread.currentThread();
   166         Thread t = Thread.currentThread();
   166         U.putLong(t, SEED, seed);
   167         SEED.set(t, seed);
   167         U.putInt(t, PROBE, probe);
   168         PROBE.set(t, probe);
   168     }
   169     }
   169 
   170 
   170     /**
   171     /**
   171      * Returns the current thread's {@code ThreadLocalRandom}.
   172      * Returns the current thread's {@code ThreadLocalRandom}.
   172      *
   173      *
   173      * @return the current thread's {@code ThreadLocalRandom}
   174      * @return the current thread's {@code ThreadLocalRandom}
   174      */
   175      */
   175     public static ThreadLocalRandom current() {
   176     public static ThreadLocalRandom current() {
   176         if (U.getInt(Thread.currentThread(), PROBE) == 0)
   177         if ((int) PROBE.get(Thread.currentThread()) == 0)
   177             localInit();
   178             localInit();
   178         return instance;
   179         return instance;
   179     }
   180     }
   180 
   181 
   181     /**
   182     /**
   190             throw new UnsupportedOperationException();
   191             throw new UnsupportedOperationException();
   191     }
   192     }
   192 
   193 
   193     final long nextSeed() {
   194     final long nextSeed() {
   194         Thread t; long r; // read and update per-thread seed
   195         Thread t; long r; // read and update per-thread seed
   195         U.putLong(t = Thread.currentThread(), SEED,
   196         SEED.set(t = Thread.currentThread(),
   196                   r = U.getLong(t, SEED) + GAMMA);
   197                  (r = (long) SEED.get(t)) + GAMMA);
   197         return r;
   198         return r;
   198     }
   199     }
   199 
   200 
   200     /**
   201     /**
   201      * Generates a pseudorandom number with the indicated number of
   202      * Generates a pseudorandom number with the indicated number of
   936      * Returns the probe value for the current thread without forcing
   937      * Returns the probe value for the current thread without forcing
   937      * initialization. Note that invoking ThreadLocalRandom.current()
   938      * initialization. Note that invoking ThreadLocalRandom.current()
   938      * can be used to force initialization on zero return.
   939      * can be used to force initialization on zero return.
   939      */
   940      */
   940     static final int getProbe() {
   941     static final int getProbe() {
   941         return U.getInt(Thread.currentThread(), PROBE);
   942         return (int) PROBE.get(Thread.currentThread());
   942     }
   943     }
   943 
   944 
   944     /**
   945     /**
   945      * Pseudo-randomly advances and records the given probe value for the
   946      * Pseudo-randomly advances and records the given probe value for the
   946      * given thread.
   947      * given thread.
   947      */
   948      */
   948     static final int advanceProbe(int probe) {
   949     static final int advanceProbe(int probe) {
   949         probe ^= probe << 13;   // xorshift
   950         probe ^= probe << 13;   // xorshift
   950         probe ^= probe >>> 17;
   951         probe ^= probe >>> 17;
   951         probe ^= probe << 5;
   952         probe ^= probe << 5;
   952         U.putInt(Thread.currentThread(), PROBE, probe);
   953         PROBE.set(Thread.currentThread(), probe);
   953         return probe;
   954         return probe;
   954     }
   955     }
   955 
   956 
   956     /**
   957     /**
   957      * Returns the pseudo-randomly initialized or updated secondary seed.
   958      * Returns the pseudo-randomly initialized or updated secondary seed.
   958      */
   959      */
   959     static final int nextSecondarySeed() {
   960     static final int nextSecondarySeed() {
   960         int r;
   961         int r;
   961         Thread t = Thread.currentThread();
   962         Thread t = Thread.currentThread();
   962         if ((r = U.getInt(t, SECONDARY)) != 0) {
   963         if ((r = (int) SECONDARY.get(t)) != 0) {
   963             r ^= r << 13;   // xorshift
   964             r ^= r << 13;   // xorshift
   964             r ^= r >>> 17;
   965             r ^= r >>> 17;
   965             r ^= r << 5;
   966             r ^= r << 5;
   966         }
   967         }
   967         else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
   968         else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
   968             r = 1; // avoid zero
   969             r = 1; // avoid zero
   969         U.putInt(t, SECONDARY, r);
   970         SECONDARY.set(t, r);
   970         return r;
   971         return r;
   971     }
   972     }
   972 
   973 
   973     // Support for other package-private ThreadLocal access
   974     // Support for other package-private ThreadLocal access
   974 
   975 
   975     /**
   976     /**
   976      * Erases ThreadLocals by nulling out Thread maps.
   977      * Erases ThreadLocals by nulling out Thread maps.
   977      */
   978      */
   978     static final void eraseThreadLocals(Thread thread) {
   979     static final void eraseThreadLocals(Thread thread) {
   979         U.putObject(thread, THREADLOCALS, null);
   980         THREADLOCALS.set(thread, null);
   980         U.putObject(thread, INHERITABLETHREADLOCALS, null);
   981         INHERITABLETHREADLOCALS.set(thread, null);
   981     }
   982     }
   982 
   983 
   983     static final void setInheritedAccessControlContext(Thread thread,
   984     static final void setInheritedAccessControlContext(Thread thread,
   984                                                        AccessControlContext acc) {
   985                                                        AccessControlContext acc) {
   985         U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
   986         INHERITEDACCESSCONTROLCONTEXT.setRelease(thread, acc);
   986     }
       
   987 
       
   988     /**
       
   989      * Returns a new group with the system ThreadGroup (the
       
   990      * topmost, parent-less group) as parent.  Uses Unsafe to
       
   991      * traverse Thread.group and ThreadGroup.parent fields.
       
   992      */
       
   993     static final ThreadGroup createThreadGroup(String name) {
       
   994         if (name == null)
       
   995             throw new NullPointerException();
       
   996         try {
       
   997             long tg = U.objectFieldOffset
       
   998                 (Thread.class.getDeclaredField("group"));
       
   999             long gp = U.objectFieldOffset
       
  1000                 (ThreadGroup.class.getDeclaredField("parent"));
       
  1001             ThreadGroup group = (ThreadGroup)
       
  1002                 U.getObject(Thread.currentThread(), tg);
       
  1003             while (group != null) {
       
  1004                 ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
       
  1005                 if (parent == null)
       
  1006                     return new ThreadGroup(group, name);
       
  1007                 group = parent;
       
  1008             }
       
  1009         } catch (ReflectiveOperationException e) {
       
  1010             throw new Error(e);
       
  1011         }
       
  1012         // fall through if null as cannot-happen safeguard
       
  1013         throw new Error("Cannot create ThreadGroup");
       
  1014     }
   987     }
  1015 
   988 
  1016     // Serialization support
   989     // Serialization support
  1017 
   990 
  1018     private static final long serialVersionUID = -5851777807851030925L;
   991     private static final long serialVersionUID = -5851777807851030925L;
  1035      */
  1008      */
  1036     private void writeObject(java.io.ObjectOutputStream s)
  1009     private void writeObject(java.io.ObjectOutputStream s)
  1037         throws java.io.IOException {
  1010         throws java.io.IOException {
  1038 
  1011 
  1039         java.io.ObjectOutputStream.PutField fields = s.putFields();
  1012         java.io.ObjectOutputStream.PutField fields = s.putFields();
  1040         fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
  1013         fields.put("rnd", (long) SEED.get(Thread.currentThread()));
  1041         fields.put("initialized", true);
  1014         fields.put("initialized", true);
  1042         s.writeFields();
  1015         s.writeFields();
  1043     }
  1016     }
  1044 
  1017 
  1045     /**
  1018     /**
  1074     // IllegalArgumentException messages
  1047     // IllegalArgumentException messages
  1075     static final String BAD_BOUND = "bound must be positive";
  1048     static final String BAD_BOUND = "bound must be positive";
  1076     static final String BAD_RANGE = "bound must be greater than origin";
  1049     static final String BAD_RANGE = "bound must be greater than origin";
  1077     static final String BAD_SIZE  = "size must be non-negative";
  1050     static final String BAD_SIZE  = "size must be non-negative";
  1078 
  1051 
  1079     // Unsafe mechanics
  1052     // VarHandle mechanics
  1080     private static final Unsafe U = Unsafe.getUnsafe();
  1053     private static final VarHandle SEED;
  1081     private static final long SEED;
  1054     private static final VarHandle PROBE;
  1082     private static final long PROBE;
  1055     private static final VarHandle SECONDARY;
  1083     private static final long SECONDARY;
  1056     private static final VarHandle THREADLOCALS;
  1084     private static final long THREADLOCALS;
  1057     private static final VarHandle INHERITABLETHREADLOCALS;
  1085     private static final long INHERITABLETHREADLOCALS;
  1058     private static final VarHandle INHERITEDACCESSCONTROLCONTEXT;
  1086     private static final long INHERITEDACCESSCONTROLCONTEXT;
       
  1087     static {
  1059     static {
  1088         try {
  1060         try {
  1089             SEED = U.objectFieldOffset
  1061             MethodHandles.Lookup l = java.security.AccessController.doPrivileged(
  1090                 (Thread.class.getDeclaredField("threadLocalRandomSeed"));
  1062                     new java.security.PrivilegedAction<>() {
  1091             PROBE = U.objectFieldOffset
  1063                         public MethodHandles.Lookup run() {
  1092                 (Thread.class.getDeclaredField("threadLocalRandomProbe"));
  1064                             try {
  1093             SECONDARY = U.objectFieldOffset
  1065                                 return MethodHandles.privateLookupIn(Thread.class,
  1094                 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
  1066                                         MethodHandles.lookup());
  1095             THREADLOCALS = U.objectFieldOffset
  1067                             } catch (ReflectiveOperationException e) {
  1096                 (Thread.class.getDeclaredField("threadLocals"));
  1068                                 throw new Error(e);
  1097             INHERITABLETHREADLOCALS = U.objectFieldOffset
  1069                             }
  1098                 (Thread.class.getDeclaredField("inheritableThreadLocals"));
  1070                         }});
  1099             INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
  1071             SEED = l.findVarHandle(Thread.class,
  1100                 (Thread.class.getDeclaredField("inheritedAccessControlContext"));
  1072                     "threadLocalRandomSeed", long.class);
       
  1073             PROBE = l.findVarHandle(Thread.class,
       
  1074                     "threadLocalRandomProbe", int.class);
       
  1075             SECONDARY = l.findVarHandle(Thread.class,
       
  1076                     "threadLocalRandomSecondarySeed", int.class);
       
  1077             Class<?> tlm = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
       
  1078             THREADLOCALS = l.findVarHandle(Thread.class,
       
  1079                     "threadLocals", tlm);
       
  1080             INHERITABLETHREADLOCALS = l.findVarHandle(Thread.class,
       
  1081                     "inheritableThreadLocals", tlm);
       
  1082             INHERITEDACCESSCONTROLCONTEXT = l.findVarHandle(Thread.class,
       
  1083                     "inheritedAccessControlContext", AccessControlContext.class);
  1101         } catch (ReflectiveOperationException e) {
  1084         } catch (ReflectiveOperationException e) {
  1102             throw new Error(e);
  1085             throw new Error(e);
  1103         }
  1086         }
  1104     }
  1087     }
  1105 
  1088 
  1121                          mix64(System.nanoTime()));
  1104                          mix64(System.nanoTime()));
  1122 
  1105 
  1123     // at end of <clinit> to survive static initialization circularity
  1106     // at end of <clinit> to survive static initialization circularity
  1124     static {
  1107     static {
  1125         if (java.security.AccessController.doPrivileged(
  1108         if (java.security.AccessController.doPrivileged(
  1126             new java.security.PrivilegedAction<Boolean>() {
  1109             new java.security.PrivilegedAction<>() {
  1127                 public Boolean run() {
  1110                 public Boolean run() {
  1128                     return Boolean.getBoolean("java.util.secureRandomSeed");
  1111                     return Boolean.getBoolean("java.util.secureRandomSeed");
  1129                 }})) {
  1112                 }})) {
  1130             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
  1113             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
  1131             long s = (long)seedBytes[0] & 0xffL;
  1114             long s = (long)seedBytes[0] & 0xffL;