持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
AQS-ConditionObject
ConditionObject是AQS中另一个用于控制线程的子类,在AQS子类Sync中使用到,Condition的目的是替代Object的wait,notify,notifyAll方法,ConditionObject为Condition接口实现。
整体结构
classDiagram
class Sync {
//状态标识
-state : int;
//头节点
-head : Node;
//尾节点
-tail : Node;
//当前运行线程
-exclusiveOwnerThread : Thread
}
class Node{
//前一个节点
-prev : Node;
//后一个节点
-next : Node;
//运行线程
-thread : Thread;
//下一个等待节点
-nextWaiter Node;
}
class ConditionObject{
//头等待节点
-firstWaiter Node;
//尾等待节点
-lastWaiter Node;
}
Node --* Sync : 持有
Node --* ConditionObject : 持有
Node --< Node : 链表
Sync继承AbstractQueuedSynchronizer,是基于AQS的同步控制,为锁的基础实现。
ConditionObject持有的节点会加入Node的nextWaiter节点中。
使用时序图
sequenceDiagram
participant 线程A
participant 线程B
participant Sync
participant ConditionObject
线程A->>Sync: lock(),当前线程对应头节点
线程A->>ConditionObject: await()新建节点添加至等待队列队尾,停止当前线程
线程B->>Sync: lock(),当前线程对应头节点
线程B->>ConditionObject: signal(),释放资源
ConditionObject-->>Sync: transferForSignal转换等待队列头节点至AQS队尾
线程B->>Sync: unlock(),释放资源
线程A->>Sync: unlock(),释放资源
关键方法
阻塞线程:await
对应Object.wait(),通过AQS机制释放锁定的资源,终止当前线程,恢复后使用AQS独占模式重新锁定资源
acquireQueued:此时node节点已转换为AQS中节点
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
唤醒线程:signal
transferForSignal转换节点后await()中acquireQueued(node,savedState)操作的节点已是AQS中的节点
isHeldExclusively:子类实现.判断是否独家持有
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
实例
@Slf4j
public class LockConditionDemo {
/**
* 非公平锁,都可争夺
*/
public static final ReentrantLock lock = new ReentrantLock();
public static final Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
log.info("主程序开始");
ConditionDemoThread conditionDemoThread = new ConditionDemoThread();
conditionDemoThread.start();
Thread.sleep(1000);
LockConditionDemo.lock.lock();
log.info("主程序lock");
try{
log.info("主程序释放-Condition.signal()");
LockConditionDemo.condition.signal();
Thread.sleep(1000);
log.info("主程序释放完成");
}finally {
LockConditionDemo.lock.unlock();
}
log.info("主程序unlock");
}
}
@Slf4j
class ConditionDemoThread extends Thread{
@Override
public void run() {
LockConditionDemo.lock.lock();
log.info("线程lock ");
try{
log.info("线程开始等待-Condition.await()");
LockConditionDemo.condition.await();
log.info("线程恢复");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
LockConditionDemo.lock.unlock();
log.info("线程unlock ");
}
try {
Thread.sleep(1000);
log.info("线程结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}