为何主线程持有dt锁仍转至新线程执行?Java线程同步解析
为什么主线程持有
dt对象锁后,控制权仍转移到新线程? 其实核心原因你已经摸到边了,但有个关键细节需要纠正——先给你梳理下完全正确的执行流程,再指出你原来流程里的小错误:
关键前置知识点(先明确这些才好理解流程)
synchronized块/方法持有的是对象锁,这里主线程和新线程争抢的都是dt这个对象的锁Object.wait()是个特殊方法:调用它时,线程会主动释放当前持有的对象锁,然后进入该对象的等待队列,直到被notify()/notifyAll()唤醒;唤醒后还得重新抢到锁才能继续执行Thread.sleep()只会让线程休眠,不会释放任何锁notify()只是唤醒等待队列里的一个线程,但被唤醒的线程不会立刻跑——它得等当前持有锁的线程释放锁后,才能去抢锁,抢到了才会继续执行
正确的执行流程
- 主线程调用
dt.start(),新线程进入就绪状态,等着CPU分配时间片 - 主线程先抢到CPU时间,进入
synchronized(dt)块,成功获取dt的对象锁 - 主线程执行
dt.wait():这一步是核心!它主动把dt的锁释放了,自己钻进dt的等待队列里暂停执行 - 新线程终于能抢到
dt的锁了,进入自己的synchronized(this)块(这里的this就是dt,和主线程锁的是同一个对象) - 新线程开始跑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(),但每次主线程被唤醒后,都因为锁还在新线程手里,没法继续执行
- i=1时:给
- 新线程的while循环跑完(i=6时退出),退出
synchronized块,终于把dt的锁释放了 - 主线程这时候才抢到
dt的锁,从之前wait()的地方继续执行,打印main here again和sum = 5 - 主线程退出
synchronized块,程序结束
你的原流程里的错误点
你说“调用notify方法,但未唤醒主线程”是不对的——notify()确实唤醒了主线程,但主线程被唤醒后,必须等新线程释放锁才能继续执行。新线程在整个while循环期间(除了wait,这里新线程没调用wait)一直持有锁,直到循环结束退出synchronized块才释放,所以主线程被唤醒后一直处于“等锁”的状态,直到新线程跑完才真正继续执行。
额外提醒
- 调用
wait()/notify()/notifyAll()的前提是必须持有该对象的锁,不然会直接抛IllegalMonitorStateException - 如果有多个线程在等同一个对象的锁,建议用
notifyAll(),避免某些线程一直被“遗忘”在等待队列里 - 线程被唤醒后,是从
wait()方法的下一行开始执行,但必须先重新获取锁,这一点很容易被忽略
内容的提问来源于stack exchange,提问作者ghostrider
相关产品推荐
相关产品推荐

