AQS主要是一个同步的处理队列,保证了线程的安全 AQS又主要分为独占式和共享式
独占式或者共享式 都要重写继承AQS的方法
- tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
- tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
- tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
独占式 共享式都是维护一个内存可见性的 state 变量 0变1 是占有 获得锁
独占式 尝试获取state 如果获取不到就加入CHL队列 其实是一个双端双向链表 先尝试加入CLH队列 如果加不进去 就自旋CAS加入 加入后 再做一个自旋CAS的处理 里面有两个部分 要么是可以获取到锁了(发现是可以获取的 要求也要是头结点 非首节点最后获取不到 还会自旋CAS可能又阻塞掉了) 返回 接着走业务代码 要么是把线程阻塞掉
其次 是tryRelease 释放 如果把state更改成功 把1改成0 就尝试唤醒后面的线程 解除阻塞 LockSupport.unpark()然后原来的线程就会重新接着自旋CAS
共享式 尝试获取state 如果返回结果state>0 说明获得了锁并且还可以获得锁 如果=0 说明获得了锁 但是 不能再获得锁了 如果<0 说明不能获得锁 不能获得锁 就会加入CLH队列
唤醒的操作 也是基于自旋CAS操作的 因为有多个线程会同时做唤醒操作 所以要让他们都操作成功 就要自旋CAS 这一点和独占式不太一样