You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何synchronized方法内调用wait会导致Java单元测试失败

问题根因

Java 中对象的wait()方法有一个核心特性:在同步块/同步方法内调用wait()时,当前持有锁的线程会立刻释放锁,进入等待状态;直到超时时间结束(或者被notify()/notifyAll()唤醒),线程才会重新竞争锁,拿到锁后才会继续执行wait()之后的代码。

结合你的代码场景,执行逻辑如下:

  • incrementSynchronized是实例同步方法,锁对象是你创建的MyCounter实例counter
  • 第一个线程抢到锁进入方法,先读取当前count值赋值给局部变量temp,随后调用wait(100),此时它立即释放了counter的锁
  • 第二个线程马上就能抢到锁进入方法,此时第一个线程还没完成count的修改,所以第二个线程读取到的temp和第一个线程完全相同,接着它也调用wait(100)释放锁
  • 以此类推,100个线程里会有大量线程读取到相同的count初始值,等100ms超时后,各个线程被唤醒,拿到锁后执行count = temp + 1,多个线程最终都是把同一个旧值加1,所以最终的count值远小于100,测试断言失败。

为什么移除wait()后测试正常

移除wait(100)后,线程拿到锁之后会连续执行temp = count→count = temp + 1的完整逻辑,全程不会释放锁,直到方法执行结束才会把锁让给下一个线程,所有累加操作都是原子生效的,最终count值就是100,测试通过。

修复方案

如果你确实需要在累加前等待100ms,不要用wait(),换成Thread.sleep(100)即可:Thread.sleep()不会释放当前持有的锁,能保证整个累加操作的原子性,测试就能正常通过。


内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:15:06