ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/Random.java
(Generate patch)

Comparing jsr166/src/main/java/util/Random.java (file contents):
Revision 1.2 by tim, Fri Aug 8 20:05:07 2003 UTC vs.
Revision 1.9 by dl, Sat Oct 1 18:09:46 2005 UTC

# Line 1 | Line 1
1   /*
2 < * @(#)Random.java      1.38 02/03/04
2 > * @(#)Random.java      1.44 05/02/01
3   *
4 < * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
4 > * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5   * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6   */
7  
8   package java.util;
9   import java.io.*;
10 < import sun.misc.Unsafe;
10 > import java.util.concurrent.atomic.AtomicLong;
11  
12   /**
13   * An instance of this class is used to generate a stream of
# Line 33 | Line 33 | import sun.misc.Unsafe;
33   * class <code>Math</code> simpler to use.
34   *
35   * @author  Frank Yellin
36 < * @version 1.38, 03/04/02
36 > * @version 1.44, 02/01/05
37   * @see     java.lang.Math#random()
38   * @since   JDK1.0
39   */
# Line 42 | Line 42 | class Random implements java.io.Serializ
42      /** use serialVersionUID from JDK 1.1 for interoperability */
43      static final long serialVersionUID = 3905348978240129619L;
44  
45    // Setup to use Unsafe.compareAndSwapLong to update seed.
46    private static final Unsafe unsafe =  Unsafe.getUnsafe();
47    private static final long seedOffset;
48    static {
49      try {
50        seedOffset =
51          unsafe.objectFieldOffset(Random.class.getDeclaredField("seed"));
52      } catch(Exception ex) { throw new Error(ex); }
53    }
54
45      /**
46       * The internal state associated with this pseudorandom number generator.
47       * (The specs for the methods in this class describe the ongoing
# Line 59 | Line 49 | class Random implements java.io.Serializ
49       *
50       * @serial
51       */
52 <    private volatile long seed;
52 >    private AtomicLong seed;
53  
54      private final static long multiplier = 0x5DEECE66DL;
55      private final static long addend = 0xBL;
56      private final static long mask = (1L << 48) - 1;
57  
58 <    /**
59 <     * Creates a new random number generator. Its seed is initialized to
60 <     * a value based on the current time:
61 <     * <blockquote><pre>
72 <     * public Random() { this(System.currentTimeMillis()); }</pre></blockquote>
73 <     * Two Random objects created within the same millisecond will have
74 <     * the same sequence of random numbers.
75 <     *
76 <     * @see     java.lang.System#currentTimeMillis()
58 >    /**
59 >     * Creates a new random number generator. This constructor sets
60 >     * the seed of the random number generator to a value very likely
61 >     * to be distinct from any other invocation of this constructor.
62       */
63 <    public Random() { this(System.currentTimeMillis()); }
63 >    public Random() { this(++seedUniquifier + System.nanoTime()); }
64 >    private static volatile long seedUniquifier = 8682522807148012L;
65  
66      /**
67       * Creates a new random number generator using a single
# Line 89 | Line 75 | class Random implements java.io.Serializ
75       * @see     java.util.Random#setSeed(long)
76       */
77      public Random(long seed) {
78 +        this.seed = new AtomicLong(0L);
79          setSeed(seed);
80      }
81  
82      /**
83 <     * Sets the seed of this random number generator using a single
84 <     * <code>long</code> seed. The general contract of <tt>setSeed</tt>
85 <     * is that it alters the state of this random number generator
86 <     * object so as to be in exactly the same state as if it had just
87 <     * been created with the argument <tt>seed</tt> as a seed. The method
88 <     * <tt>setSeed</tt> is implemented by class Random as follows:
89 <     * <blockquote><pre>
90 <     * synchronized public void setSeed(long seed) {
91 <     *       this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
92 <     *       haveNextNextGaussian = false;
93 <     * }</pre></blockquote>
94 <     * The implementation of <tt>setSeed</tt> by class <tt>Random</tt>
95 <     * happens to use only 48 bits of the given seed. In general, however,
109 <     * an overriding method may use all 64 bits of the long argument
110 <     * as a seed value.
111 <     *
112 <     * Note: Even though seed is updated atomically, this method
113 <     *       must still be synchronized to ensure correct semantics
114 <     *       of haveNextNextGaussian.
83 >     * Sets the seed of this random number generator using a single
84 >     * <code>long</code> seed. The general contract of
85 >     * <tt>setSeed</tt> is that it alters the state of this random
86 >     * number generator object so as to be in exactly the same state
87 >     * as if it had just been created with the argument <tt>seed</tt>
88 >     * as a seed. The method <tt>setSeed</tt> is implemented by class
89 >     * Random using a thread-safe update of the seed to <code> (seed *
90 >     * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)</code> and clearing the
91 >     * <code>haveNextNextGaussian</code> flag used by {@link
92 >     * #nextGaussian}.  The implementation of <tt>setSeed</tt> by class
93 >     * <tt>Random</tt> happens to use only 48 bits of the given
94 >     * seed. In general, however, an overriding method may use all 64
95 >     * bits of the long argument as a seed value.
96       *
97       * @param   seed   the initial seed.
98       */
99      synchronized public void setSeed(long seed) {
100 <        this.seed = (seed ^ multiplier) & mask;
100 >        seed = (seed ^ multiplier) & mask;
101 >        this.seed.set(seed);
102          haveNextNextGaussian = false;
103      }
104  
105      /**
106       * Generates the next pseudorandom number. Subclass should
107 <     * override this, as this is used by all other methods.<p>
108 <     * The general contract of <tt>next</tt> is that it returns an
109 <     * <tt>int</tt> value and if the argument bits is between <tt>1</tt>
110 <     * and <tt>32</tt> (inclusive), then that many low-order bits of the
111 <     * returned value will be (approximately) independently chosen bit
112 <     * values, each of which is (approximately) equally likely to be
113 <     * <tt>0</tt> or <tt>1</tt>. The method <tt>next</tt> is implemented
114 <     * by class <tt>Random</tt> as follows:
115 <     * <blockquote><pre>
116 <     * synchronized protected int next(int bits) {
117 <     *       seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
118 <     *       return (int)(seed >>> (48 - bits));
119 <     * }</pre></blockquote>
120 <     * This is a linear congruential pseudorandom number generator, as
139 <     * defined by D. H. Lehmer and described by Donald E. Knuth in <i>The
140 <     * Art of Computer Programming,</i> Volume 2: <i>Seminumerical
107 >     * override this, as this is used by all other methods.<p> The
108 >     * general contract of <tt>next</tt> is that it returns an
109 >     * <tt>int</tt> value and if the argument bits is between
110 >     * <tt>1</tt> and <tt>32</tt> (inclusive), then that many
111 >     * low-order bits of the returned value will be (approximately)
112 >     * independently chosen bit values, each of which is
113 >     * (approximately) equally likely to be <tt>0</tt> or
114 >     * <tt>1</tt>. The method <tt>next</tt> is implemented by class
115 >     * <tt>Random</tt> using a thread-safe update of the seed to <code>
116 >     * (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)</code> and
117 >     * returning <code>(int)(seed >>> (48 - bits))</code>.  This is a
118 >     * linear congruential pseudorandom number generator, as defined
119 >     * by D. H. Lehmer and described by Donald E. Knuth in <i>The Art
120 >     * of Computer Programming,</i> Volume 2: <i>Seminumerical
121       * Algorithms</i>, section 3.2.1.
122       *
123       * @param   bits random bits
# Line 146 | Line 126 | class Random implements java.io.Serializ
126       */
127      protected int next(int bits) {
128          long oldseed, nextseed;
129 +        AtomicLong seed = this.seed;
130          do {
131 <          oldseed = seed;
132 <          nextseed = (oldseed * multiplier + addend) & mask;
133 <        } while (!unsafe.compareAndSwapLong(this, seedOffset,
153 <                                           oldseed, nextseed));
131 >            oldseed = seed.get();
132 >            nextseed = (oldseed * multiplier + addend) & mask;
133 >        } while (!seed.compareAndSet(oldseed, nextseed));
134          return (int)(nextseed >>> (48 - bits));
135      }
136  
# Line 405 | Line 385 | class Random implements java.io.Serializ
385       * <tt>double</tt> value, chosen from (approximately) the usual
386       * normal distribution with mean <tt>0.0</tt> and standard deviation
387       * <tt>1.0</tt>, is pseudorandomly generated and returned. The method
388 <     * <tt>nextGaussian</tt> is implemented by class <tt>Random</tt> as follows:
388 >     * <tt>nextGaussian</tt> is implemented by class <tt>Random</tt> as if
389 >     * by a threadsafe version of the following:
390       * <blockquote><pre>
391 <     * synchronized public double nextGaussian() {
391 >     * public double nextGaussian() {
392       *    if (haveNextNextGaussian) {
393       *            haveNextNextGaussian = false;
394       *            return nextNextGaussian;
# Line 418 | Line 399 | class Random implements java.io.Serializ
399       *                    v2 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
400       *                    s = v1 * v1 + v2 * v2;
401       *            } while (s >= 1 || s == 0);
402 <     *            double multiplier = Math.sqrt(-2 * Math.log(s)/s);
402 >     *            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
403       *            nextNextGaussian = v2 * multiplier;
404       *            haveNextNextGaussian = true;
405       *            return v1 * multiplier;
# Line 428 | Line 409 | class Random implements java.io.Serializ
409       * G. Marsaglia, as described by Donald E. Knuth in <i>The Art of
410       * Computer Programming</i>, Volume 2: <i>Seminumerical Algorithms</i>,
411       * section 3.4.1, subsection C, algorithm P. Note that it generates two
412 <     * independent values at the cost of only one call to <tt>Math.log</tt>
413 <     * and one call to <tt>Math.sqrt</tt>.
412 >     * independent values at the cost of only one call to <tt>StrictMath.log</tt>
413 >     * and one call to <tt>StrictMath.sqrt</tt>.
414       *
415       * @return  the next pseudorandom, Gaussian ("normally") distributed
416       *          <code>double</code> value with mean <code>0.0</code> and
# Line 448 | Line 429 | class Random implements java.io.Serializ
429                  v2 = 2 * nextDouble() - 1; // between -1 and 1
430                  s = v1 * v1 + v2 * v2;
431              } while (s >= 1 || s == 0);
432 <            double multiplier = Math.sqrt(-2 * Math.log(s)/s);
432 >            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
433              nextNextGaussian = v2 * multiplier;
434              haveNextNextGaussian = true;
435              return v1 * multiplier;
# Line 486 | Line 467 | class Random implements java.io.Serializ
467          if (seedVal < 0)
468            throw new java.io.StreamCorruptedException(
469                                "Random: invalid seed");
470 <        seed = seedVal;
470 >        seed = new AtomicLong(seedVal);
471          nextNextGaussian = fields.get("nextNextGaussian", 0.0);
472          haveNextNextGaussian = fields.get("haveNextNextGaussian", false);
473      }
# Line 501 | Line 482 | class Random implements java.io.Serializ
482      synchronized private void writeObject(ObjectOutputStream s) throws IOException {
483          // set the values of the Serializable fields
484          ObjectOutputStream.PutField fields = s.putFields();
485 <        fields.put("seed", seed);
485 >        fields.put("seed", seed.get());
486          fields.put("nextNextGaussian", nextNextGaussian);
487          fields.put("haveNextNextGaussian", haveNextNextGaussian);
488  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines