AQS学习笔记之独占锁

作用

  参与 共享锁 acquireShared() 和 独占锁 acquire() 的抢锁逻辑,
  具体的抢锁逻辑不作实现,只对第一次抢锁未抢到锁线程做处理,第一次抢锁就抢到的线程就不需要遇到AQS了

方法、属性:

       AQS属性:
                
                head 头结点   已经入队的节点只有前置节点是头节点的情况下才有机会抢锁
                
                tail  尾结点  入队就从这里入
       
       Node属性:
       
                pre 前置节点,
                next 后置节点
                waitStatus 状态   0代表已经入队的第一个线程持有锁
                                       1代表下一个线程取消了排队
                                       -1代表可以下一个线程可以抢锁了
                                       -2代表下一个线程正在中断,等待唤醒
                                       -3代表抢的是共享锁,后面的线程抢共享锁的线程都可以得到锁
                exclusive 是否独占模式
       
       
       AQS方法:
                acquire():未入队的线程抢锁使用这个方法
                           请求锁,如果未请求成功且以独占模式入队成功则当前线程先中断
                        
             
                        
                 acquireQueued():已经入队的线程抢锁使用这个方法
                 
                 
                 addWaiter():      描述:     先尝试用CAS进行快速入队,失败则调用enq()方法入队
                 enq():              描述 for循环+CAS 入队

独占锁的获取和释放

方法名描述
acquire() 请求获取锁,如果未获取成功 &&以独占模式入队成功且前置节点不是头节点 则中断当前线程
tryAcquire(arg) 尝试请求锁,该方法在AQS中不做实现
acquireQueued(Node,arg) 已经入队的线程使用for循环+CAS操作尝试调用tryAcquire()请求锁:当入队后发现前置节点是头节点则尝试请求锁,如果请求成功则出队,如果失败则使用shouldParkAfterFailedAcquire(pred,node)判断是否需要中断当前线程,如果不需要则在循环中继续尝试获取锁
shouldParkAfterFailedAcquire(pred,node) 如果前置节点的waitStatus是SIGNAL则表示当前线程需要中断,或者前置节点被取消了(取消状态是1)就向前查找还在排队的节点,这个时候当前线程还有机会再尝试获取锁
addWaiter(mode) 先尝试使用CAS进行快速入队,失败则调用enq()进行入队
enq(node) 使用for循环加CAS操作进行入队
release(arg) 释放锁:调用tryRelease尝试释放锁,如果释放成功了则判断有没有线程在排队,如果有则使用LockSupport.unpark(Thread)唤醒队列中第一个线程
tryRelease(arg) 尝试释放锁,该方法在AQS中不作实现

总结:
对于线程来说最重要的是 获取锁,中断,唤醒,释放锁

   获取锁:线程入队前会尝试请求一次锁
              入队后会检查当前线程的前置节点是不是head节点,如果是且waitStatus是SIGNAL,则尝试获取锁,
              
    中断:线程在未抢到锁的时候中断(废话)
    唤醒:(只有未抢到锁的线程且已经入队的线程)线程在队列中的第一个,且持有锁的线程释放了锁
    释放锁:已经抢到锁的线程调用release()方法就释放了
节点入队:第一次抢锁未抢到锁就会入队
节点出队:第一次没抢到锁,后来 抢到锁了或者取消抢锁了就会出队
posted @ 2019-03-28 17:39  英长  阅读(179)  评论(0编辑  收藏  举报