conditionobject 实例本身内存开销极小(约24–32字节),不随等待线程数增长;真正占用内存的是 await 时创建的 node 节点(约32字节/个),且各 condition 等待队列相互隔离。

Condition 对象本身内存开销很小,通常只包含几个引用字段和状态变量,单个 ConditionObject 实例在 HotSpot JVM 上占用约 24–32 字节(含对象头、对齐填充),不随等待线程数量线性增长。
Condition 实例本身的结构很轻量
ReentrantLock 的 ConditionObject 是其静态内部类,没有额外的堆外资源或缓存。它主要持有:
- 一个指向等待队列首节点(firstWaiter)的 volatile 引用
- 一个指向等待队列尾节点(lastWaiter)的 volatile 引用
- 无其他实例字段(如计数器、时间戳等)
因此,新建一个 lock.newCondition() 几乎不带来可观测的内存压力。
真正影响内存的是等待中的线程节点
当线程调用 await(),会创建一个 Node 节点加入该 Condition 的等待队列。每个 Node 是一个普通对象,包含:
- 前驱/后继指针(prev/nextWaiter)
- 线程引用(thread)
- 等待状态(waitStatus)
- 其他标记字段
在 64 位 JVM(开启指针压缩)下,一个 Node 实例典型大小为 32 字节左右。若有 1000 个线程在某个 Condition 上 await,就会多出约 32 KB 的堆内存占用——这部分是可回收的,一旦被 signal 唤醒并转入同步队列,Node 会被移除或复用。
多个 Condition 不共享等待队列
每个 lock.newCondition() 返回独立的 ConditionObject,各自维护自己的等待链表。这意味着:
- 定义 5 个 Condition,就多 5 个轻量对象(≈160 字节)
- 但它们的等待节点完全隔离——不会互相干扰,也不会共用内存
- 相比 synchronized 的单一 waitSet,Condition 的“分队列”设计反而减少了无效唤醒带来的上下文切换开销,间接节省 CPU 和内存带宽
注意:长期阻塞会隐式延长对象生命周期
若线程长时间 await(如超时设置极大或 never signal),对应的 Node 和 Thread 引用会持续存在于堆中,可能推迟 GC 回收。尤其当 Thread 持有大对象引用时,会造成间接内存驻留。这不是 Condition 本身的问题,而是使用模式导致的。
建议配合超时 await(如 await(30, SECONDS))或定期检查中断,避免无限期挂起。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











