1 |
|
/* |
2 |
< |
* @(#)Random.java 1.38 02/03/04 |
2 |
> |
* %W% %E% |
3 |
|
* |
4 |
< |
* Copyright 2002 Sun Microsystems, Inc. All rights reserved. |
4 |
> |
* Copyright 2003 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 |
33 |
|
* class <code>Math</code> simpler to use. |
34 |
|
* |
35 |
|
* @author Frank Yellin |
36 |
< |
* @version 1.38, 03/04/02 |
36 |
> |
* @version %I%, %G% |
37 |
|
* @see java.lang.Math#random() |
38 |
|
* @since JDK1.0 |
39 |
|
*/ |
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 |
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 |
75 |
|
* @see java.util.Random#setSeed(long) |
76 |
|
*/ |
77 |
|
public Random(long seed) { |
78 |
+ |
this.seed = new AtomicLong(0L); |
79 |
|
setSeed(seed); |
80 |
|
} |
81 |
|
|
96 |
|
* an overriding method may use all 64 bits of the long argument |
97 |
|
* as a seed value. |
98 |
|
* |
99 |
< |
* Note: Even though seed is updated atomically, this method |
99 |
> |
* Note: Although the seed value is an AtomicLong, this method |
100 |
|
* must still be synchronized to ensure correct semantics |
101 |
|
* of haveNextNextGaussian. |
102 |
|
* |
103 |
|
* @param seed the initial seed. |
104 |
|
*/ |
105 |
|
synchronized public void setSeed(long seed) { |
106 |
< |
this.seed = (seed ^ multiplier) & mask; |
106 |
> |
seed = (seed ^ multiplier) & mask; |
107 |
> |
this.seed.set(seed); |
108 |
|
haveNextNextGaussian = false; |
109 |
|
} |
110 |
|
|
135 |
|
protected int next(int bits) { |
136 |
|
long oldseed, nextseed; |
137 |
|
do { |
138 |
< |
oldseed = seed; |
138 |
> |
oldseed = seed.get(); |
139 |
|
nextseed = (oldseed * multiplier + addend) & mask; |
140 |
< |
} while (!unsafe.compareAndSwapLong(this, seedOffset, |
153 |
< |
oldseed, nextseed)); |
140 |
> |
} while (!seed.compareAndSet(oldseed, nextseed)); |
141 |
|
return (int)(nextseed >>> (48 - bits)); |
142 |
|
} |
143 |
|
|
473 |
|
if (seedVal < 0) |
474 |
|
throw new java.io.StreamCorruptedException( |
475 |
|
"Random: invalid seed"); |
476 |
< |
seed = seedVal; |
476 |
> |
seed = new AtomicLong(seedVal); |
477 |
|
nextNextGaussian = fields.get("nextNextGaussian", 0.0); |
478 |
|
haveNextNextGaussian = fields.get("haveNextNextGaussian", false); |
479 |
|
} |
488 |
|
synchronized private void writeObject(ObjectOutputStream s) throws IOException { |
489 |
|
// set the values of the Serializable fields |
490 |
|
ObjectOutputStream.PutField fields = s.putFields(); |
491 |
< |
fields.put("seed", seed); |
491 |
> |
fields.put("seed", seed.get()); |
492 |
|
fields.put("nextNextGaussian", nextNextGaussian); |
493 |
|
fields.put("haveNextNextGaussian", haveNextNextGaussian); |
494 |
|
|