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 /** |
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; |
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; |