linkedblockingqueue采用双锁双condition设计以提升生产者-消费者并发性能:putlock与takelock分离读写操作,notempty和notfull精准通知,atomicinteger保证count可见性,支持中断响应。

LinkedBlockingQueue 的双锁(takeLock / putLock)+ 双 Condition(notEmpty / notFull)设计,本质是为了解决生产者-消费者场景下的高并发读写冲突,通过读写分离降低锁竞争,提升吞吐量。
双锁隔离读写操作
队列内部维护两个独立的 ReentrantLock: - putLock 仅保护入队(offer/put)逻辑,包括修改 tail、插入新节点、更新 count; - takeLock 仅保护出队(poll/take)逻辑,包括修改 head、移除节点、更新 count。
两个锁互不干扰,允许生产者和消费者**同时执行**——只要队列非满且非空,就能并发操作。这比单锁(如 ArrayBlockingQueue)显著减少线程阻塞。
Condition 与状态解耦
每个锁绑定一个专属 Condition:
- notFull(关联 putLock):当队列满时,生产者 await;有元素被消费后,消费者 signalNotFull;
- notEmpty(关联 takeLock):当队列空时,消费者 await;有新元素入队后,生产者 signalNotEmpty。
这种绑定关系确保: - signal 操作总在对应锁的持有下进行,避免虚假唤醒; - 等待/通知严格按操作类型划分,不会因共用 Condition 导致误唤醒或漏唤醒。
count 的原子性与内存可见性
count 字段被声明为 AtomicInteger,而非用锁保护,原因在于:
- 入队/出队都需增减 count,但每次只由一个线程修改(putLock 或 takeLock 保证);
- AtomicInteger 提供 volatile 语义 + CAS,确保 count 修改对所有线程立即可见;
- 避免为 count 单独加锁,进一步减少同步开销。
注意:count 的读取(如 size())虽不加锁,但返回的是“某一时刻快照”,不保证强一致性——这是性能与一致性的合理权衡。
中断与响应式等待
take/put 方法支持线程中断:
- await() 被中断时抛出 InterruptedException,上层可及时处理;
- signal 之后若等待线程已中断,Condition 会清理其等待节点,避免资源泄漏;
- 中断信号不会破坏锁状态,putLock/takeLock 的持有关系依然清晰可控。
这种设计让 LinkedBlockingQueue 在响应式系统或需优雅关闭的场景中更可靠。
不复杂但容易忽略:双锁不是为了“锁得更细”,而是让读写路径真正并行;Condition 不是装饰,而是状态变更的精准信令机制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











