非公平锁和公平锁

  非公平锁和公平锁的一些理解

  一、什么是非公平锁

    场景:线程1,加了锁,然后线程2尝试枷锁,失败后进入等待队列,处于阻塞的状态,后来线程1释放了锁,准备来唤醒线程2重新尝试加锁。

    注意一点:此时线程2可能还停留在等待队列里,还没开始重新加锁呢!

    然而,不幸的事情发生了,这时半路杀出一个程咬金,来了一个线程3,线程3突然尝试ReentractLock发起加锁操作,此时会发生什么事情呢?

    很简单,线程2还没来得及重新尝试加锁呢,也就是说,还没来得及重新执行CAS操作将State变成从0变成1呢,线程3冲上来就直接一个CAS操作,尝试将state值从0变成1,结果还是成功了。

    一旦CAS操作成功,线程3就会将加锁线程设置为他自己。

    明明人家线程2规规矩矩排队领锁,结果你线程3不守规矩,部分青红皂白就直接跑过来抢先加锁了。

    这就导致线程2被唤醒后,重新尝试加锁执行CAS操作,结果毫不疑问,失败!

    一旦加锁失败,会导致线程2继续在等待队列里面,不断等着,等着释放线程3的锁之后,再来唤醒线程2,。

    上述的锁策略:就是默认非公平锁。

    在非公平锁的策略下,不一定说先来排队的线程就得到机会加锁,而是出现各种线程随机抢占的情况。

    那如果要实现公平锁的策略,怎么办呢,就是在ReentrantLock对象的时候,传入一个true即可。

    ReentrantLock lock=new ReentrantLock(true);

    此时,就会让他使用公平锁策略,那公平锁策略是啥意思呢。

  二、什么是公平锁

    回到刚刚的情况,如果线程1 刚刚释放锁之后,线程2还没来得及重新加锁的状态。

    同样此时来一个线程3,突然杀出来,想要加锁。如果是公平锁策略,那么此时线程3不会像闷头清一样加锁。

    他会先判断一下,AQS的等待队列里,有没有认真排队,如果有人在排队的话,说明我前面的兄弟正想要加锁呢。

    如果AQS的队列里面真的有线程排着队,那我线程3就不能和二愣子一样直接加锁了。因为咱们是公平策略,得按照先来后到的顺序依次排队,谁先入队,谁就先从队列里出来加锁。

    所以此时线程一判断,发现队列里有人排队,自己就会乖乖的排到队列后面去,而不是贸然加锁。

    接着,线程2不就被唤醒了Ma,他会重新的尝试进行CAS加锁,此时没人跟它抢,他当然可以加锁成功了。

    这就是公平锁的策略,过来加锁的线程都是按照先来后到的顺序,依次进入等待队列中,不会盲目的乱占加锁,非常的公平。

  三、总结

    Java并发包里面很多锁的策略,默认都是非公平的,也就是时候可能后来的线程先加锁,先来的线程后加锁。

    而一般情况下,非公平锁的策略都没有什么太大的问题。但是大家要对这策略做到心里有数,在开发的时候,需要考虑和权衡使用公平策略还是非公平策略。

posted @ 2021-03-08 07:03  GDOUJKZZ  阅读(351)  评论(0编辑  收藏  举报