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

为何主线程持有dt锁仍转至新线程执行?Java线程同步解析

为什么主线程持有dt对象锁后,控制权仍转移到新线程?

其实核心原因你已经摸到边了,但有个关键细节需要纠正——先给你梳理下完全正确的执行流程,再指出你原来流程里的小错误:

关键前置知识点(先明确这些才好理解流程)

  • synchronized块/方法持有的是对象锁,这里主线程和新线程争抢的都是dt这个对象的锁
  • Object.wait()是个特殊方法:调用它时,线程会主动释放当前持有的对象锁,然后进入该对象的等待队列,直到被notify()/notifyAll()唤醒;唤醒后还得重新抢到锁才能继续执行
  • Thread.sleep()只会让线程休眠,不会释放任何锁
  • notify()只是唤醒等待队列里的一个线程,但被唤醒的线程不会立刻跑——它得等当前持有锁的线程释放锁后,才能去抢锁,抢到了才会继续执行

正确的执行流程

  1. 主线程调用dt.start(),新线程进入就绪状态,等着CPU分配时间片
  2. 主线程先抢到CPU时间,进入synchronized(dt)块,成功获取dt的对象锁
  3. 主线程执行dt.wait():这一步是核心!它主动把dt的锁释放了,自己钻进dt的等待队列里暂停执行
  4. 新线程终于能抢到dt的锁了,进入自己的synchronized(this)块(这里的this就是dt,和主线程锁的是同一个对象)
  5. 新线程开始跑while循环(i从1到5):
    • i=1时:给sum赋值1,休眠1秒(锁还攥在手里),醒来打印Woke up from sleep,因为i<2,不执行notify()
    • i=2时:赋值sum=2,休眠打印后,执行this.notify()——这时候确实唤醒了主线程,但主线程醒了也没用,因为新线程还拿着dt的锁呢,主线程只能等着抢锁
    • i=3/4/5时:重复赋值、休眠、打印,每次都会执行notify(),但每次主线程被唤醒后,都因为锁还在新线程手里,没法继续执行
  6. 新线程的while循环跑完(i=6时退出),退出synchronized块,终于把dt的锁释放了
  7. 主线程这时候才抢到dt的锁,从之前wait()的地方继续执行,打印main here again和sum = 5
  8. 主线程退出synchronized块,程序结束

你的原流程里的错误点

你说“调用notify方法,但未唤醒主线程”是不对的——notify()确实唤醒了主线程,但主线程被唤醒后,必须等新线程释放锁才能继续执行。新线程在整个while循环期间(除了wait,这里新线程没调用wait)一直持有锁,直到循环结束退出synchronized块才释放,所以主线程被唤醒后一直处于“等锁”的状态,直到新线程跑完才真正继续执行。

额外提醒

  • 调用wait()/notify()/notifyAll()的前提是必须持有该对象的锁,不然会直接抛IllegalMonitorStateException
  • 如果有多个线程在等同一个对象的锁,建议用notifyAll(),避免某些线程一直被“遗忘”在等待队列里
  • 线程被唤醒后,是从wait()方法的下一行开始执行,但必须先重新获取锁,这一点很容易被忽略

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:06:35