当前位置:网站首页>Things like random

Things like random

2022-07-07 00:01:00 Bulst

Last article , We explained several ways to generate random numbers .

Next , Let's take a closer look Random How is it realized .

Before the start , Let's make a small demo

    public static void main(String[] args) {
    
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
    
            int randomValue = random.nextInt(10);
            System.out.println(randomValue);
        }
    }

This procedure , How many times do you run , It generates different numbers .

And you add a seed to it , It generates the same sequence .

such as

    public static void main(String[] args) {
    
        Random random = new Random(1);
        for (int i = 0; i < 10; i++) {
    
            int randomValue = random.nextInt(10);
            System.out.println(randomValue);
        }
    }

Why is that ?

You must have read the previous article , It's already clear .

because Random Default constructor , Use time as seed , So the values generated each time are different .

    /** * 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());
    }

Let's take a look at how to generate random numbers .

	// bound: The range of random numbers 
    public int nextInt(int bound) {
    
        if (bound <= 0)
            throw new IllegalArgumentException(BadBound);
		//  track 【 Make new seeds from old ones 】
        int r = next(31);

		//  Calculate the random number according to the new seed 
        int m = bound - 1;
        if ((bound & m) == 0)  // i.e., bound is a power of 2
            r = (int)((bound * (long)r) >> 31);
        else {
    
            for (int u = r;
                 u - (r = u % bound) + m < 0;
                 u = next(31))
                ;
        }

In the case of a single thread, each call nextInt New seeds are calculated from old seeds , This can guarantee the randomness of random numbers .

But in multithreading, multiple threads may take the same old seed to calculate the new seed , This will cause multiple threads to produce the same new seeds , Because the algorithm of generating random numbers is fixed , Therefore, it will cause multiple threads to produce the same random value .

therefore int r = next(31); To be atomic , That is, when multiple threads calculate a new seed based on the same old seed , After the new seed of the first thread is calculated , The second thread discards its old seeds , Use the new seed of the first thread to calculate your new seed , By analogy , Only this is guaranteed , To ensure that the random number generated by multithreading is random .

track 【 Make new seeds from old ones 】

protected int next(int bits) {
    
    long oldseed, nextseed;
    //  Atomic classes 
    AtomicLong seed = this.seed;
    do {
    
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}

ah , this …

Typical CAS Well .

Forget it , Eating out , Wait for the next one , Let's have a good talk CAS.

原网站

版权声明
本文为[Bulst]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061639544853.html