Alice52 / java-ocean

java-tutorial .We intend to explain Java knowledge in this repository.
MIT License
0 stars 0 forks source link

[common] random #219

Closed Alice52 closed 3 years ago

Alice52 commented 3 years ago

Random: 线程安全 CAS

  1. 一般都是全局使用某一个 Random 实例, 在高并发下可能会导致线程阻塞

  2. 随机原理

    • 对一个”随机种子”进行固定的算术和位运算, 到随机结, 再使用这个结果作为下一次随机的种子
  3. core code

    protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
            // CAS 更新下一次随机的种子
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

ThreadLocalRandom

  1. 线程安全

    • Thread 对象内存在着一个属性 threadLocalRandomSeed: 此线程专属的随机种子
    • ThreadLocalRandom 类加载时就可以通过 offset 找到每个线程自己的随机种子
    • 该线程产生一个随机种子之后会将新的随机种子放入该线程: UNSAFE实现, 不是使用get/set修改是会导致违反类的封闭性原则
  2. 过程

    • ThreadLocalRandom 会获取当前线程的 seed, 计算得到结果, 之后将此结果赋值给该线程的 seed[方便下次使用]
    • 两个线程之间不影响, 也是线程安全的, 且不会出现线程阻塞问题
  3. core code

    public long nextLong() {
        return mix64(nextSeed());
    }
    
    final long nextSeed() {
        Thread t = Thread.currentThread();
        long r = UNSAFE.getLong(t, SEED) + GAMMA;
        UNSAFE.putLong(t, SEED, r); 
    }

reference

  1. https://blog.csdn.net/xiaolong2230/article/details/97002564
Alice52 commented 3 years ago

unsafe 12L

  1. Object o = new Object(): 8/4 + 8 + 8/4 + 0 = 8/4 + 16

  2. 对象的内存布局

    • 对象头: 8 * 8 =64bit
    • 类型指针: 8 / 4 compressClassPointers
    • 实例数据: 0
    • 对齐: 使其为 8 的倍数
  3. 数组对象

    • 多一个数组长度: 4 字节且与压缩无关