最近在整理Java并发知识的时候突然发现AQS和Monitor这两套锁机制在设计上有着惊人的相似性。准确地说它们都用了双队列的思路来处理锁的竞争和等待但具体实现上又各有各的玩法。队列的对应关系先上一张对照表看看它们是怎么一对一的synchronized / MonitorAQS / ReentrantLock_owner当前持锁线程state exclusiveOwnerThread_EntryList抢锁失败的线程sync queue_WaitSet调用wait()后挂起的线程Condition queue_Monitor里的_EntryList大致对应AQS的同步队列sync queue。当线程抢锁失败后就会被扔进这个队列里等着。_Monitor里的_WaitSet则对应AQS的条件队列Condition queue。线程已经拿到过锁了但因为某个条件不满足主动调用wait()挂起就待在这里。所以从功能分工来看它们简直就是一个模子里刻出来的抢锁失败 → 进竞争队列排队条件不满足主动等待 → 进条件队列等通知被唤醒后 → 再滚回竞争队列重新抢这大概就是英雄所见略同吧。状态那些事很多人容易把BLOCKED和WAITING搞混包括我之前也是。 后来想了一个简单的判断方法看它在等什么。BLOCKED等的是进入synchronized的机会通俗点说就是卡在锁门口进不去WAITING等的是某个事件发生比如别人notify()、unpark()、或者join()结束有意思的是AQS同步队列里的线程虽然本质上也在等锁但线程状态通常不是BLOCKED而是WAITING。这是为什么因为AQS不是靠monitor enter卡在对象锁门口它是靠CAS尝试拿锁失败后入队LockSupport.park()挂起而park()挂起出来的线程状态大家都懂通常是WAITING或TIMED_WAITING。这就和synchronized那种直接BLOCKED的方式不一样了。总结一下队列含义常见状态Monitor.EntryList等进入synchronizedBLOCKEDMonitor.WaitSet已拿锁调用wait()等待条件WAITING / TIMED_WAITINGAQS sync queuelock()失败后排队等锁WAITING / TIMED_WAITINGAQS condition queueawait()后等待条件WAITING / TIMED_WAITING说白了它们都是双队列的设计思路但Monitor更底层、更重量级AQS则提供了更好的封装和扩展性。理解了这个对应关系再去看ReentrantLock、CountDownLatch这些AQS的实现类就会清晰很多。本来是想分开整理的结果写着写着发现它们居然这么像看来并发编程里很多看似不同的东西底层逻辑都是相通的。