1 |
|
/* |
2 |
< |
* @(#)Random.java 1.38 02/03/04 |
2 |
> |
* @(#)Random.java 1.39 03/01/23 |
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 1.39, 01/23/03 |
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; |
79 |
|
* @see java.util.Random#setSeed(long) |
80 |
|
*/ |
81 |
|
public Random(long seed) { |
82 |
+ |
this.seed = new AtomicLong(0L); |
83 |
|
setSeed(seed); |
84 |
|
} |
85 |
|
|
100 |
|
* an overriding method may use all 64 bits of the long argument |
101 |
|
* as a seed value. |
102 |
|
* |
103 |
< |
* Note: Even though seed is updated atomically, this method |
103 |
> |
* Note: Although the seed value is an AtomicLong, this method |
104 |
|
* must still be synchronized to ensure correct semantics |
105 |
|
* of haveNextNextGaussian. |
106 |
|
* |
107 |
|
* @param seed the initial seed. |
108 |
|
*/ |
109 |
|
synchronized public void setSeed(long seed) { |
110 |
< |
this.seed = (seed ^ multiplier) & mask; |
110 |
> |
seed = (seed ^ multiplier) & mask; |
111 |
> |
this.seed.set(seed); |
112 |
|
haveNextNextGaussian = false; |
113 |
|
} |
114 |
|
|
139 |
|
protected int next(int bits) { |
140 |
|
long oldseed, nextseed; |
141 |
|
do { |
142 |
< |
oldseed = seed; |
142 |
> |
oldseed = seed.get(); |
143 |
|
nextseed = (oldseed * multiplier + addend) & mask; |
144 |
< |
} while (!unsafe.compareAndSwapLong(this, seedOffset, |
153 |
< |
oldseed, nextseed)); |
144 |
> |
} while (!seed.compareAndSet(oldseed, nextseed)); |
145 |
|
return (int)(nextseed >>> (48 - bits)); |
146 |
|
} |
147 |
|
|
477 |
|
if (seedVal < 0) |
478 |
|
throw new java.io.StreamCorruptedException( |
479 |
|
"Random: invalid seed"); |
480 |
< |
seed = seedVal; |
480 |
> |
seed = new AtomicLong(seedVal); |
481 |
|
nextNextGaussian = fields.get("nextNextGaussian", 0.0); |
482 |
|
haveNextNextGaussian = fields.get("haveNextNextGaussian", false); |
483 |
|
} |
492 |
|
synchronized private void writeObject(ObjectOutputStream s) throws IOException { |
493 |
|
// set the values of the Serializable fields |
494 |
|
ObjectOutputStream.PutField fields = s.putFields(); |
495 |
< |
fields.put("seed", seed); |
495 |
> |
fields.put("seed", seed.get()); |
496 |
|
fields.put("nextNextGaussian", nextNextGaussian); |
497 |
|
fields.put("haveNextNextGaussian", haveNextNextGaussian); |
498 |
|
|