AQS源码解读
2021-12-02 16:42:32 0 举报
AQS源码解读
作者其他创作
大纲/内容
第一次进入lock()会执行font color=\"#ff0000\
线程B被唤醒后,我们回到当初parkAndCheckInterrupt()方法内,LockSupport.park(this);线程B被中断的地方
首先来看线程A(客户A)的执行流程ReentrantLock 不传参默认是非公平锁,调用 lock.lock() 方法最终会执行 NonfairSync 的 lock()方法
因为是第二次上锁,state=1,font color=\"#ff0000\
首先来看tryAcquire(arg)方法,入参arg=1;接着分析font color=\"#ff0000\
首先入参 acquires=1final Thread current = Thread.currentThread(); 获取到当前线程ThreadBint c = getState(); =1所以不会进入 if (c == 0) { } 流程else if (current == getExclusiveOwnerThread()) {}判断当前持有线程是否为本线程,由于当前持有线程为ThreadA,非ThreadB,返回false最终 nonfairTryAcquire() 方法在这里返回 false
setExclusiveOwnerThread() 方法:将拥有 lock 锁的线程修改为线程 A
下面解读线程B争抢锁的流程,线程B的上锁是第二次lock
第一次for循环
tryRelease 也是AbstractQueuedSynchronizer 中定义的方法,抛出了个异常,需要查看其具体实现方法unparkSuccessor(h)
线程C跟线程B类似,都是执行acquire方法,tryAcquire方法跟线程B也一样返回false,但是addWaiter有点区别
第二次for循环
回到parkAndCheckInterrupt()的上一层,acquireQueued()方法的for(;;)再一次进行自旋
第一次循环
这里简单复习一下CAS,通过 Unsafe 提供的 compareAndSwapXxx() 方法保证修改操作的原子性(通过 CPU 原语保证),如果变量的值等于期望值,则修改变量的值为 update,并返回 true;若不等,则返回 false。this 代表当前对象,stateOffset 表示 state 变量在该对象中的偏移量
最后的最后,我们需要等待线程B的解锁,唤醒线程C的过程也类似
可以看到哨兵节点已经没有任何引用,等待GC回收,线程B持有了锁,state=1,顾客B成了新的哨兵节点
接着时间来到了ThreadA 的unlock阶段
0 条评论
下一页