Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[common] random #219

Closed
Alice52 opened this issue Jul 14, 2021 · 1 comment
Closed

[common] random #219

Alice52 opened this issue Jul 14, 2021 · 1 comment
Assignees
Labels
Java java implement important than extend

Comments

@Alice52
Copy link
Owner

Alice52 commented Jul 14, 2021

  • 以对象作为 key 是可能会造成内存泄漏的
  • UNSAFE 未经保护地改变内存,会引起别的方法在使用这一段内存时报错: 里面的方法都是线程安全的
    // 使用 unsafe 将 Test 类 value 属性的位置设置成了 long 型值 2333,
    // 而当使用 value 属性时,虚拟机会将这一块内存解析为 String 对象,
    // 原 String 对象对象头的结构被打乱了,解析对象失败抛出了错误,
    // 更严重的问题是报错信息中没有类名行号等信息,在复杂项目中排查这种问题真如同大海捞针
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        // Test 类是一个随手写的测试类,只有一个 String 类型的测试类
        Test test = new Test();
        test.ttt = "12345";
        unsafe.putLong(test, 12L, 2333L);
        System.out.println(test.value);
    }

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 Alice52 added the Java java implement important than extend label Jul 14, 2021
@Alice52 Alice52 self-assigned this Jul 14, 2021
@Alice52 Alice52 closed this as completed Jul 14, 2021
@Alice52
Copy link
Owner Author

Alice52 commented Jul 15, 2021

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 字节且与压缩无关

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Java java implement important than extend
Projects
None yet
Development

No branches or pull requests

1 participant