Java.util.Random implementation principle

Summary

Instances of this class are used to generate streams of pseudo-random numbers. The class uses a 48 bit seed, which is modified by a linear congruence formula. If two instances of Random with the same seed created, each instance of the same method call sequences they will generate and returns the number of the same sequence into a sequence with a method call, they will generate and return the same sequence number.

Sample

Public class RandomTest static void main {public (String[] args) {testRandom (System.out.println); testRandom ("data interchange for trade"); (System.out.println); testRandom ("data interchange for trade"); (public); static void (testRandom)} {Random random = new Random (1) (int; for i=0; i< 5; i++) {System.out.print (random.nextInt) + ("/t"); ("System.out.println");}}}

Output result:

Java.util.Random implementation principle

From the results it is found that the sequence of random numbers obtained is consistent as long as the seeds are the same. Is a pseudo random number realization, not a real random number.

Random source code analysis

Class Random structure

Class Random implements java.io.Serializable final AtomicLong {private seed; private static final long multiplier private static final long = 0x5DEECE66DL; addend = 0xBL; private = static final long mask (1L < < 48) - 1; private static final AtomicLong seedUniquifier = new AtomicLong (8682522807148012L);

Parametric construction method

Public Random (long seed) {if (getClass) (New = = Random.class) this.seed = 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;};

By introduction of a seed, to generate a random number, using the above example, random number sequence generated by the same seed, if want to use each generated sequence is not the same, it can only pass a different seed.

Nonparametric construction method

Public (Random) this (seedUniquifier) ^ {(System.nanoTime)} (private); static long (seedUniquifier) {/ / L’Ecuyer, “Tables of Linear Congruential Generators of Different Sizes and Good Lattice / Structure, for (1999; current = seedUniquifier.get; long) {(long); next = current * 181783497276652981L; if (seedUniquifier.compareAndSet (current, next)) return next;}}

Through the source code, construction method of no arguments, which help us to automatically produce a seed, and through the CAS way to ensure every access to the spin, the seed is not the same, so as to ensure each new (Random) random sequence acquisition is not consistent.

NextInt () method: get the int random number

Public int nextInt (return) {next}; (32) protected int next (int bits) {long oldseed nextseed; AtomicLong seed = this.seed; do = {oldseed (seed.get); nextseed = (oldseed * multiplier + addend) & Mask;} while (! Seed.compareAndSet (oldseed, nextseed)); return (int) (nextseed > > > (48 – bits));}

From the code, we can find that as long as the seed is determined, the number of generated each time is generated by a fixed algorithm, so as long as the seed is determined, each generated sequence is fixed.

Each time the seed is updated, the CAS is used to update it, and if the environment is highly concurrent, performance is a problem.

Security issues

Just imagine, if this is a lottery platform, as long as the seed is determined, each have the same sequence. So you can use this vulnerability to predict the next lottery number, so that some people are vulnerable to loopholes.

JDK recommends that you use SecureRandom as far as possible to generate random numbers.

SecureRandom

SecureRandom is a strong random number generator, the main application of the scene: the number of data used for security purposes, such as generating a secret key or the session (session ID), marked above “pseudo random number” safety, has given us to expose the weak random number generator safety problem, and use SecureRandom such a strong random number the generator will greatly reduce the risks.

There are two important factors for generating high intensity random numbers: seeds and algorithms. There are a lot of algorithms, and how you choose seeds is a crucial factor. Such as Random, its seed is System.currentTimeMillis (), so its random number is predictable, is a weak pseudo random number. Generate ideas
strong pseudo-random number: collect all kinds of information of the computer keyboard input time, memory usage, disk free space, IO delay, process number, the number of threads, CPU clock, to get an approximate random seed, mainly to unpredictability.

The simple thing is that using the encryption algorithm generates a very long random seed, so that you can’t guess the seed, and you can’t deduce the random number.

Random performance issues

From the Random source code, we found that every time we get the random number, we use the CAS method to update the value of the seed. In this case, there will be a lot of CAS retry in a highly concurrent environment, resulting in performance degradation. At this time it is recommended that you use the ThreadLocalRandom class to generate random numbers.

ThreadLocalRandom implementation principle

Thread class

Java.util.Random implementation principle

There is a threadLocalRandomSeed attribute in the Thread class.

ThreadLocalRandom structure

Java.util.Random implementation principle

The SEED variable is the offset of the threadLocalRandomSeed in the Thread object.

ThreadLocalRandom.nextSeed () method

Java.util.Random implementation principle

From this method, we find that each thread’s seed value is stored in the threadLocalRandomSeed property of the Thread object.

conclusion

Because the seeds in ThreadLocalRandom are stored in Thread objects, CAS is not used when the Random object is highly concurrent to ensure that the values obtained each time are inconsistent.
each thread maintains one of its own seed, when each thread needs to get a random number, get the current thread from the current Thread object in the seed, obtain the random number, performance is greatly improved.

Instances of this class are used to generate streams of pseudo-random numbers. The class uses a 48 bit seed, which is modified by a linear congruence formula. If two instances of Random with the same seed created, each instance of the same method call sequences they will generate and returns the number of the same sequence into a sequence with a method call, they will generate and return the same sequence number.