先来段使用
@Test
public void testReentrantLockCondition(){
ReentrantLock reentrantLock=new ReentrantLock();
Condition condition=reentrantLock.newCondition();
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
System.out.println("线程1加锁成功");
condition.await();
System.out.println("线程1条件成立");
reentrantLock.unlock();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000l);
reentrantLock.lock();
System.out.println("线程2加锁成功");
condition.signal();
System.out.println("线程2发放条件许可");
reentrantLock.unlock();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
for(;;);
}
从条件队列申请来看看他究竟做了什么
public Condition newCondition() {
return sync.newCondition();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
这一步主要在AbstractQueuedSynchronizer中创建了一个ConditionObject对象
在看condition.await();方法的具体处理
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();//创建线程对象
int savedState = fullyRelease(node);//解除该线程持有的锁,返回重入次数
int interruptMode = 0;
while (!isOnSyncQueue(node)) {//判断是否存入AQS阻塞队列
LockSupport.park(this);//阻塞,等待唤醒
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)//判断是否中断
break;
}
//acquireQueued这个方法在[添加链接描述](https://editor.csdn.net/md/?articleId=106258239)文章中已经讲过了通过循环方式一致去获取独占量(锁),这里不再解析
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;//设置中断模式
if (node.nextWaiter != null) // 清除已取消的节点clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);//中断
}
流程图
在看condition.signal();方法的具体处理
public final void signal() {
if (!isHeldExclusively())//判断是否持有锁
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);//添加入AQS队列如果不成功一直往下找,知道找到成功的
}
final boolean transferForSignal(Node node) {
//CAS更新等待状态
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
Node p = enq(node);//添加入AQS队列,返回上一个节点
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))//上一个节点为取消状态,替换该状态为取消,解除阻塞
LockSupport.unpark(node.thread);
//如果上一个队列不是取消,那该线程只能阻塞等待AQS队列陆续处理过来
return true;
}
流程图