Java之AQS-创新互联
是用来实现锁或者其它同步器组件的公共基础部分的抽象实现,整体就是一个抽象的FIFO队列来完成资源获取线程的安排工作,并通过一个int类变量表示持有锁的状态。
ReentranLock:
CountDownLatch
ReentrantReadWriteLock:
Semaphore
抢到资源的线程直接使用处理业务,抢不到资源的必然涉及一种排队等候机制。抢占资源失败的线程继续去等待(类似银行业务办理窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等候),但等候线程仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)
如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到的锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态封装成队列的结点对象(Node),通过CAS、自旋以及LockSupport.park()的方式,维护state变量的状态,使并发达到同步的效果。
第一步:
第二步:创建的是公平锁还是非公平锁
第三:以非公平锁ReentrantLock()为例作为突破走起,方法lock()
对比公平锁和非公平锁的tryAcquire()方法的实现代码,其实差别就在于非公平锁获取锁时公平锁中少了一个判断!hasQueuedPredecessors(),此方法中判断了是否需要排队,导致公平锁和非公平锁的差异如下:
公平锁:公平锁讲究先来先到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入等待队列中;
非公平锁:不管是否有等待队列,如果可以获取锁,则立刻占有锁对象。也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还是需要参加竞争锁(存在线程竞争的情况下),后来的线程可能不讲武德插队夺锁了。
第四:线程使用lock方法来加锁
以下截图为非公平锁的
第五:acquire()方法
第六:tryAcquire方法
第六,如果线程使用nonfairTryAcquire方法抢占资源失败,则使用addWaiter方法将线程加入等待队列
第一次调用enq方法之后会形成以下的样子:
第七:acquireQueued()方法
第八:使用unlock方法来释放锁
队列中唤醒的线程再去抢占锁
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
当前名称:Java之AQS-创新互联
文章链接:http://hbruida.cn/article/ggseg.html