}
}, “thread-C”).start();
}
public static void main(String[] args){
new NotifyDemo().startThreadA();
}
}
以上就是本次实战用到的demo,代码功能简述如下:
-
启动线程A,取得锁之后先启动线程B再执行wait()方法,释放锁并等待;
-
线程B启动之后会等待锁,A线程执行wait()之后,线程B取得锁,然后启动线程C,再执行notify唤醒线程A,最后退出synchronize代码块,释放锁;
-
线程C启动之后就一直在等待锁,这时候线程B还没有退出synchronize代码块,锁还在线程B手里;
-
线程A在线程B执行notify()之后就一直在等待锁,这时候线程B还没有退出synchronize代码块,锁还在线程B手里;
-
线程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源码可以聚焦主线,不要被一些支线的次要的代码卡住(例如一些异常处理,监控和上报等):
-
线程A在wait()的时候做了什么?
-
线程C启动后,由于此时线程B持有锁,那么线程C此时在干啥?
-
线程B在notify()的时候做了什么?
-
线程B释放锁的时候做了什么?
源码中最重要的注释信息
在源码中有段注释堪称是整篇文章最重要的说明,请大家始终记住这段信息,处处都用得上:
ObjectWaiter对象存在于WaitSe