zoukankan      html  css  js  c++  java
  • 非公平锁和公平锁

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

      一、什么是非公平锁

        场景:线程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并发包里面很多锁的策略,默认都是非公平的,也就是时候可能后来的线程先加锁,先来的线程后加锁。

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

    终极目标:世界大同
  • 相关阅读:
    滚动相册
    智能拼图
    连连看
    魔法色块
    ASP.NET Session的七点认识
    从11月开始windows update速度缓慢,中国反击?
    WM实现文件关联
    与黄河老师合影
    ubuntu8.04笔记本开启无线网卡记得开网卡的电源
    无法在Web服务器上启动调试,与Web服务器通信时出现身份验证错误
  • 原文地址:https://www.cnblogs.com/gdouzz/p/14497721.html
Copyright © 2011-2022 走看看