src/share/classes/java/util/concurrent/ThreadLocalRandom.java

Print this page




 117      * compatibility across versions.
 118      *
 119      * Implementations of non-core methods are mostly the same as in
 120      * SplittableRandom, that were in part derived from a previous
 121      * version of this class.
 122      *
 123      * The nextLocalGaussian ThreadLocal supports the very rarely used
 124      * nextGaussian method by providing a holder for the second of a
 125      * pair of them. As is true for the base class version of this
 126      * method, this time/space tradeoff is probably never worthwhile,
 127      * but we provide identical statistical properties.
 128      */
 129 
 130     /** Generates per-thread initialization/probe field */
 131     private static final AtomicInteger probeGenerator =
 132         new AtomicInteger();
 133 
 134     /**
 135      * The next seed for default constructors.
 136      */
 137     private static final AtomicLong seeder = new AtomicLong(initialSeed());
 138 
 139     private static long initialSeed() {
 140         String pp = java.security.AccessController.doPrivileged(
 141                 new sun.security.action.GetPropertyAction(
 142                         "java.util.secureRandomSeed"));
 143         if (pp != null && pp.equalsIgnoreCase("true")) {
 144             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
 145             long s = (long)(seedBytes[0]) & 0xffL;
 146             for (int i = 1; i < 8; ++i)
 147                 s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
 148             return s;
 149         }
 150         long h = 0L;
 151         try {
 152             Enumeration<NetworkInterface> ifcs =
 153                     NetworkInterface.getNetworkInterfaces();
 154             boolean retry = false; // retry once if getHardwareAddress is null
 155             while (ifcs.hasMoreElements()) {
 156                 NetworkInterface ifc = ifcs.nextElement();
 157                 if (!ifc.isVirtual()) { // skip fake addresses
 158                     byte[] bs = ifc.getHardwareAddress();
 159                     if (bs != null) {
 160                         int n = bs.length;
 161                         int m = Math.min(n >>> 1, 4);
 162                         for (int i = 0; i < m; ++i)
 163                             h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
 164                         if (m < 4)
 165                             h = (h << 8) ^ bs[n-1-m];
 166                         h = mix64(h);
 167                         break;
 168                     }
 169                     else if (!retry)
 170                         retry = true;
 171                     else
 172                         break;
 173                 }
 174             }
 175         } catch (Exception ignore) {
 176         }
 177         return (h ^ mix64(System.currentTimeMillis()) ^
 178                 mix64(System.nanoTime()));
 179     }
 180 
 181     /**
 182      * The seed increment
 183      */
 184     private static final long GAMMA = 0x9e3779b97f4a7c15L;
 185 
 186     /**
 187      * The increment for generating probe values
 188      */
 189     private static final int PROBE_INCREMENT = 0x9e3779b9;
 190 
 191     /**
 192      * The increment of seeder per new instance
 193      */
 194     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
 195 
 196     // Constants from SplittableRandom
 197     private static final double DOUBLE_UNIT = 0x1.0p-53;  // 1.0  / (1L << 53)
 198     private static final float  FLOAT_UNIT  = 0x1.0p-24f; // 1.0f / (1 << 24)
 199 


1062      * @param s the stream
1063      * @throws java.io.IOException if an I/O error occurs
1064      */
1065     private void writeObject(java.io.ObjectOutputStream s)
1066         throws java.io.IOException {
1067 
1068         java.io.ObjectOutputStream.PutField fields = s.putFields();
1069         fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
1070         fields.put("initialized", true);
1071         s.writeFields();
1072     }
1073 
1074     /**
1075      * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
1076      * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
1077      */
1078     private Object readResolve() {
1079         return current();
1080     }
1081 
1082     // Unsafe mechanics
1083     private static final sun.misc.Unsafe UNSAFE;
1084     private static final long SEED;
1085     private static final long PROBE;
1086     private static final long SECONDARY;
1087     static {
1088         try {
1089             UNSAFE = sun.misc.Unsafe.getUnsafe();
1090             Class<?> tk = Thread.class;
1091             SEED = UNSAFE.objectFieldOffset
1092                 (tk.getDeclaredField("threadLocalRandomSeed"));
1093             PROBE = UNSAFE.objectFieldOffset
1094                 (tk.getDeclaredField("threadLocalRandomProbe"));
1095             SECONDARY = UNSAFE.objectFieldOffset
1096                 (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
1097         } catch (Exception e) {
1098             throw new Error(e);
1099         }






























1100     }















1101 }


 117      * compatibility across versions.
 118      *
 119      * Implementations of non-core methods are mostly the same as in
 120      * SplittableRandom, that were in part derived from a previous
 121      * version of this class.
 122      *
 123      * The nextLocalGaussian ThreadLocal supports the very rarely used
 124      * nextGaussian method by providing a holder for the second of a
 125      * pair of them. As is true for the base class version of this
 126      * method, this time/space tradeoff is probably never worthwhile,
 127      * but we provide identical statistical properties.
 128      */
 129 
 130     /** Generates per-thread initialization/probe field */
 131     private static final AtomicInteger probeGenerator =
 132         new AtomicInteger();
 133 
 134     /**
 135      * The next seed for default constructors.
 136      */
 137     private static final AtomicLong seeder =
 138         // this is just intermediate value - see static block at end of file...
 139         new AtomicLong(mix64(System.currentTimeMillis()) ^






































 140                        mix64(System.nanoTime()));

 141 
 142     /**
 143      * The seed increment
 144      */
 145     private static final long GAMMA = 0x9e3779b97f4a7c15L;
 146 
 147     /**
 148      * The increment for generating probe values
 149      */
 150     private static final int PROBE_INCREMENT = 0x9e3779b9;
 151 
 152     /**
 153      * The increment of seeder per new instance
 154      */
 155     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
 156 
 157     // Constants from SplittableRandom
 158     private static final double DOUBLE_UNIT = 0x1.0p-53;  // 1.0  / (1L << 53)
 159     private static final float  FLOAT_UNIT  = 0x1.0p-24f; // 1.0f / (1 << 24)
 160 


1023      * @param s the stream
1024      * @throws java.io.IOException if an I/O error occurs
1025      */
1026     private void writeObject(java.io.ObjectOutputStream s)
1027         throws java.io.IOException {
1028 
1029         java.io.ObjectOutputStream.PutField fields = s.putFields();
1030         fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
1031         fields.put("initialized", true);
1032         s.writeFields();
1033     }
1034 
1035     /**
1036      * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
1037      * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
1038      */
1039     private Object readResolve() {
1040         return current();
1041     }
1042 
1043     // Unsafe mechanics and "seeder" initialization
1044     private static final sun.misc.Unsafe UNSAFE;
1045     private static final long SEED;
1046     private static final long PROBE;
1047     private static final long SECONDARY;
1048     static {
1049         try {
1050             UNSAFE = sun.misc.Unsafe.getUnsafe();
1051             Class<?> tk = Thread.class;
1052             SEED = UNSAFE.objectFieldOffset
1053                 (tk.getDeclaredField("threadLocalRandomSeed"));
1054             PROBE = UNSAFE.objectFieldOffset
1055                 (tk.getDeclaredField("threadLocalRandomProbe"));
1056             SECONDARY = UNSAFE.objectFieldOffset
1057                 (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
1058         } catch (Exception e) {
1059             throw new Error(e);
1060         }
1061 
1062         // finish initialization of "seeder"
1063         String pp = java.security.AccessController.doPrivileged(
1064             new sun.security.action.GetPropertyAction(
1065                 "java.util.secureRandomSeed"));
1066         if (pp != null && pp.equalsIgnoreCase("true")) {
1067             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
1068             long s = (long)(seedBytes[0]) & 0xffL;
1069             for (int i = 1; i < 8; ++i)
1070                 s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
1071             seeder.set(s);
1072         } else {
1073             try {
1074                 long h = 0L;
1075                 Enumeration<NetworkInterface> ifcs =
1076                     NetworkInterface.getNetworkInterfaces();
1077                 boolean retry = false; // retry once if getHardwareAddress is null
1078                 while (ifcs.hasMoreElements()) {
1079                     NetworkInterface ifc = ifcs.nextElement();
1080                     if (!ifc.isVirtual()) { // skip fake addresses
1081                         byte[] bs = ifc.getHardwareAddress();
1082                         if (bs != null) {
1083                             int n = bs.length;
1084                             int m = Math.min(n >>> 1, 4);
1085                             for (int i = 0; i < m; ++i)
1086                                 h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
1087                             if (m < 4)
1088                                 h = (h << 8) ^ bs[n-1-m];
1089                             h = mix64(h);
1090                             break;
1091                         }
1092                         else if (!retry)
1093                             retry = true;
1094                         else
1095                             break;
1096                     }
1097                 }
1098                 seeder.set(seeder.get() ^ h);
1099             } catch (Exception ignore) {
1100             }
1101         }
1102         // trigger re-initialization of thread-local state
1103         // in case TLR has already been used in current thread
1104         UNSAFE.putInt(Thread.currentThread(), PROBE, 0);
1105     }
1106 
1107 }