--- jsr166/src/main/java/util/Random.java 2008/05/18 23:59:57 1.22 +++ jsr166/src/main/java/util/Random.java 2011/06/06 19:00:28 1.30 @@ -1,12 +1,12 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this + * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -18,9 +18,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. */ package java.util; @@ -32,7 +32,7 @@ import sun.misc.Unsafe; * An instance of this class is used to generate a stream of * pseudorandom numbers. The class uses a 48-bit seed, which is * modified using a linear congruential formula. (See Donald Knuth, - * The Art of Computer Programming, Volume 3, Section 3.2.1.) + * The Art of Computer Programming, Volume 2, Section 3.2.1.) *

* If two instances of {@code Random} are created with the same * seed, and the same sequence of method calls is made for each, they @@ -50,6 +50,18 @@ import sun.misc.Unsafe; *

* Many applications will find the method {@link Math#random} simpler to use. * + *

Instances of {@code java.util.Random} are threadsafe. + * However, the concurrent use of the same {@code java.util.Random} + * instance across threads may encounter contention and consequent + * poor performance. Consider instead using + * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded + * designs. + * + *

Instances of {@code java.util.Random} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} to + * get a cryptographically secure pseudo-random number generator for use + * by security-sensitive applications. + * * @author Frank Yellin * @since 1.0 */ @@ -65,17 +77,32 @@ class Random implements java.io.Serializ */ private final AtomicLong seed; - private final static long multiplier = 0x5DEECE66DL; - private final static long addend = 0xBL; - private final static long mask = (1L << 48) - 1; + private static final long multiplier = 0x5DEECE66DL; + private static final long addend = 0xBL; + private static final long mask = (1L << 48) - 1; /** * Creates a new random number generator. This constructor sets * the seed of the random number generator to a value very likely * to be distinct from any other invocation of this constructor. */ - public Random() { this(++seedUniquifier + System.nanoTime()); } - private static volatile long seedUniquifier = 8682522807148012L; + public Random() { + this(seedUniquifier() ^ System.nanoTime()); + } + + private static long seedUniquifier() { + // L'Ecuyer, "Tables of Linear Congruential Generators of + // Different Sizes and Good Lattice Structure", 1999 + for (;;) { + long current = seedUniquifier.get(); + long next = current * 181783497276652981L; + if (seedUniquifier.compareAndSet(current, next)) + return next; + } + } + + private static final AtomicLong seedUniquifier + = new AtomicLong(8682522807148012L); /** * Creates a new random number generator using a single {@code long} seed. @@ -91,8 +118,17 @@ class Random implements java.io.Serializ * @see #setSeed(long) */ public Random(long seed) { - this.seed = new AtomicLong(0L); - setSeed(seed); + if (getClass() == Random.class) + this.seed = new AtomicLong(initialScramble(seed)); + else { + // subclass might have overriden setSeed + this.seed = new AtomicLong(); + setSeed(seed); + } + } + + private static long initialScramble(long seed) { + return (seed ^ multiplier) & mask; } /** @@ -115,8 +151,7 @@ class Random implements java.io.Serializ * @param seed the initial seed */ synchronized public void setSeed(long seed) { - seed = (seed ^ multiplier) & mask; - this.seed.set(seed); + this.seed.set(initialScramble(seed)); haveNextNextGaussian = false; } @@ -256,7 +291,7 @@ class Random implements java.io.Serializ * @return the next pseudorandom, uniformly distributed {@code int} * value between {@code 0} (inclusive) and {@code n} (exclusive) * from this random number generator's sequence - * @exception IllegalArgumentException if n is not positive + * @throws IllegalArgumentException if n is not positive * @since 1.2 */ @@ -504,7 +539,7 @@ class Random implements java.io.Serializ // The seed is read in as {@code long} for // historical reasons, but it is converted to an AtomicLong. - long seedVal = (long) fields.get("seed", -1L); + long seedVal = fields.get("seed", -1L); if (seedVal < 0) throw new java.io.StreamCorruptedException( "Random: invalid seed");