Java的wait和notify学习三部曲之一:JVM源码分析

本文深入探讨Java中wait和notify的使用,通过一个实战示例分析线程A、B、C的执行流程。在JVM源码层面,解释线程A在wait()时如何进入WaitSet,线程B如何通过notify()唤醒线程,以及线程C如何尝试获取锁。文章揭示了JVM中ObjectMonitor的工作原理,包括锁的竞争、膨胀过程和线程状态转换。
摘要由CSDN通过智能技术生成

}

}, “thread-C”).start();

}

public static void main(String[] args){

new NotifyDemo().startThreadA();

}

}

以上就是本次实战用到的demo,代码功能简述如下:

  1. 启动线程A,取得锁之后先启动线程B再执行wait()方法,释放锁并等待;

  2. 线程B启动之后会等待锁,A线程执行wait()之后,线程B取得锁,然后启动线程C,再执行notify唤醒线程A,最后退出synchronize代码块,释放锁;

  3. 线程C启动之后就一直在等待锁,这时候线程B还没有退出synchronize代码块,锁还在线程B手里;

  4. 线程A在线程B执行notify()之后就一直在等待锁,这时候线程B还没有退出synchronize代码块,锁还在线程B手里;

  5. 线程B退出synchronize代码块,释放锁之后,线程A和线程C竞争锁;

把上面的代码在Openjdk8下面执行,反复执行多次,都得到以下结果:

thread-A : get lock

thread-A : start wait

thread-B : get lock

thread-C : c thread is start

thread-B : start notify

thread-B : release lock

thread-A : after wait, acquire lock again

thread-A : release lock

thread-C : get lock

thread-C : release lock

针对以上结果,问题来了:第一个问题:将以上代码反复执行多次,结果都是B释放锁之后A会先得到锁,这又是为什么呢?C为何不能先拿到锁呢?

第二个问题:线程C自开始就执行了monitorenter指令,它能得到锁是容易理解的,但是线程A呢?在wait()之后并没有没有monitorenter指令,那么它又是如何取得锁的呢?

wait()、notify()这些方法都是native方法,所以只有从JVM源码寻找答案了,本次阅读的是openjdk8的源码;

带上问题去看JVM源码

按照demo代码执行顺序,我整理了如下问题,带着这些问题去看JVM源码可以聚焦主线,不要被一些支线的次要的代码卡住(例如一些异常处理,监控和上报等):

  1. 线程A在wait()的时候做了什么?

  2. 线程C启动后,由于此时线程B持有锁,那么线程C此时在干啥?

  3. 线程B在notify()的时候做了什么?

  4. 线程B释放锁的时候做了什么?

源码中最重要的注释信息

在源码中有段注释堪称是整篇文章最重要的说明,请大家始终记住这段信息,处处都用得上:

ObjectWaiter对象存在于WaitSe

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值