参考资料:
1、深入浅出AQS之独占锁模式
https://www.jianshu.com/p/71449a7d01af
2、深入浅出AQS之共享锁模式
https://www.jianshu.com/p/1161d33fc1d0
独占式
获取过程:
1、线程调用 acquire() 方法获取同步状态 state
2、如果 tryAcquire() 返回为 false (获取失败),将会调用 addWaiter(Node.EXCLUSIVE) 将当前获取同步状态失败的线程 作为新的节点 加入 同步队列(一个双向的 FIFO 队列,用于管理同步状态)的 tail,进行自旋(for(;;))(① 当前驱节点为 head,且获取到了同步状态,则设置当前节点为 head,原来 head 的 next 指向 null ② 如果获取失败后应该被 park,且 park 成功,则当前节点被阻塞,直到被 前驱节点 唤醒)
3、 如果 tryAcquire() 返回为 true,则获取同步状态成功
释放过程:
1、线程调用 release() 方法释放同步状态 state
2、如果 tryRelease() 方法返回 true,则调用 unparkSuccessor() 唤醒 head 的后继节点
共享式
获取:
1、线程调用 acquireShared() 方法获取同步状态 state
2、如果 tryAcquireShared() < 0,则获取同步状态失败。调用 addWaiter(Node.SHARED) 将当前获取同步状态失败的线程 作为新的节点 加入 同步队列(一个双向的 FIFO 队列,用于管理同步状态)的 tail,进行自旋(for(;;))(① 当前驱节点为 head,将尝试获取同步状态(tryAcquireShared()),如果获取到了同步状态(tryAcquireShared()>= 0),则设置当前节点为 head,并依次唤醒该节点后的所有共享节点,原来 head 的 next 指向 null ② 如果获取失败后应该被 park,且 park 成功,则当前节点被阻塞,直到被 前驱节点 唤醒)
3、如果 tryAcquireShared()>= 0,则获取同步状态失败。
释放:
1、线程调用 release() 方法释放同步状态 state
2、如果 tryRelease() 方法返回 true,则 doReleasedShared ()调用 unparkSuccessor() 唤醒 head 的后继节点
独占式与共享式的区别
跟 独占式 相比,共享式 的主要特征在于当一个在等待队列中的共享节点成功获取到 state 以后(它获取到的是共享锁),它必须要依次唤醒后面所有可以跟它一起共享当前锁资源的节点,毫无疑问,这些节点必须也是在等待共享锁