(多线程)并发问题记录

1.Hash扩容算法问题:
    a.多线程put操作,get会死循环,这个可以优化掉比如扩容的时候新开一个数组,不要使用共享的那个数组
    b.多线程put可能导致get取值错误

    问题分析:
        hash冲突一般是采用链式结构来保存冲突的值,如果在遍历这个链表时,它本身是这样的 1->2->3->4->null
    遍历到3本身应该是Null的,这时候刚好有人把这个null给计算出了值,null=>1->3,这下就完了,原来3要指向null结束的,
    这下又编程指向了1,而这个1又刚好指向3,这就出现了死循环问题。

    解决方案:
        a.单线程操作
        b.多线程场景要注意加锁,比如jdk里可以使用ConCurrentHashMap 分段锁等等。

2.Random随机数重复问题
    Random类产生随机数是根据“种子数”进行一系列算法得出的,并发场景下,若种子数相同,那得出的随机数结果也必然相同。

问题分析:

        观察Random类,发现其中提供了两个构造方法,一个有参一个无参,而无参方法其实就是传入一个nanoTime作为Random的种子数 “seed”:              

有参方法:
 public Random(long seed) {
        if (getClass() == Random.class)
            this.seed = new AtomicLong(initialScramble(seed));
        else {
            // subclass might have overriden setSeed
            this.seed = new AtomicLong();
            setSeed(seed);
        }
    }



//无参方法
public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }

        System.nanoTime()方法,会返回正在运行的Java虚拟机的高分辨率时间源的当前值,以纳秒为单位。

        接下来看关键地方:

   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));
    }

这是 random.nextInt() 调用的底层方法,while 的判断条件是:当旧种子数oldseed和新种子数nextseed不同时,由新种子nextseed计算得出随机数。

可以看到,新种子数nextseed  =

(旧种子数oldseed  * multiplier(定值) + addend(定值))& mask(定值) 

那么在高并发场景下,多个线程在同一纳秒级别调用了Random,或者多个线程同时访问同一个Random方法来产生的随机数,由于oldseed相同,所计算出的随机值那也是相同的。

        解决方案:

        a.单线程操作

        b. 使用线程安全类   ThreadLocalRandom.current().nextInt(10);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值