JVM中Condition与LockSupport哪个性能更优?实验存疑求解
Condition与LockSupport性能对比实验分析
我们开展了同步调用的实验:每个线程任务等待返回自身值+1的任务回调,以此对比Condition与LockSupport的性能差异。实验结果出乎意料:二者总耗时相同,但火焰图差异极大,这是否意味着JVM未对LockSupport进行优化?

实验代码
public class LockerTest { static int max = 100000; static boolean usePark = true; static Map<Long, Long> msg = new ConcurrentHashMap<>(); static ExecutorService producer = Executors.newFixedThreadPool(4); static ExecutorService consumer = Executors.newFixedThreadPool(16); static AtomicLong record = new AtomicLong(0); static CountDownLatch latch = new CountDownLatch(max); static ReentrantLock lock = new ReentrantLock(); static Condition cond = lock.newCondition(); static Map<Long, Thread> parkMap = new ConcurrentHashMap<>(); static AtomicLong cN = new AtomicLong(0); public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); for (int num = 0; num < max; num++) { consumer.execute(() -> { long id = record.incrementAndGet(); msg.put(id, -1L); call(id); if (usePark) { Thread thread = Thread.currentThread(); parkMap.put(id, thread); while (msg.get(id) == -1) { cN.incrementAndGet(); LockSupport.park(thread); } } else { lock.lock(); try { while (msg.get(id) == -1) { cN.incrementAndGet(); cond.await(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } latch.countDown(); }); } latch.await(); consumer.shutdown(); producer.shutdown(); System.out.printf("park %s suc %s cost %s cn %s" , usePark , msg.entrySet().stream().noneMatch(entry -> entry.getKey() + 1 != entry.getValue()) , System.currentTimeMillis() - start , cN.get() ); } private static void call(long id) { producer.execute(() -> { try { Thread.sleep((id * 13) % 100); } catch (InterruptedException e) { e.printStackTrace(); } if (usePark) { msg.put(id, id + 1); LockSupport.unpark(parkMap.remove(id)); } else { lock.lock(); try { msg.put(id, id + 1); cond.signalAll(); } finally { lock.unlock(); } } }); } }
结果分析
1. 总耗时相同的原因
实验的核心瓶颈不在等待机制,而在producer线程池的处理能力:
producer仅配置4个线程,每个任务都包含Thread.sleep((id * 13) % 100)的随机延迟,这部分耗时占据了总运行时间的绝大部分。- 不管用Condition还是LockSupport,等待逻辑都是在等待producer完成计算并更新
msg,而producer的处理速度直接决定了整体耗时,因此两种方式的总耗时差异不大。
2. 火焰图差异大的原因
两种等待方式的上层逻辑差异导致了火焰图的不同:
- LockSupport版本:采用精准唤醒,每个线程仅在自己的任务完成后被单独
unpark,等待逻辑仅涉及线程状态的直接切换,栈帧更简洁。 - Condition版本:每次更新
msg后调用signalAll,会唤醒所有等待在该Condition上的线程;被唤醒的线程需要重新竞争锁、检查msg状态,大部分线程会再次进入await,这涉及到锁队列、条件队列的维护操作,栈帧中会包含更多与锁调度相关的逻辑。
3. JVM对LockSupport的优化情况
JVM完全对LockSupport做了深度优化:
- LockSupport的
park/unpark是JUC同步框架(如AQS、ReentrantLock)的底层基础,是native方法,直接与操作系统的线程调度机制交互,能高效实现线程的挂起与唤醒。 - 实际上,Condition的
await方法最终也是通过LockSupport实现的,只是Condition额外封装了锁竞争、条件队列管理的逻辑,这才是两者火焰图差异的根源,而非JVM未优化LockSupport。
实验优化建议
如果要更精准对比两种等待方式的性能,建议移除Thread.sleep逻辑,让瓶颈集中在等待与唤醒的调度上,此时LockSupport的精准唤醒优势会更明显,总耗时会低于使用signalAll的Condition版本。
内容的提问来源于stack exchange,提问作者moonsky
相关产品推荐
相关产品推荐

