-
线程C启动后,由于此时线程B持有锁,那么线程C此时在干啥?
-
线程B在notify()的时候做了什么?
-
线程B释放锁的时候做了什么?
源码中最重要的注释信息
在源码中有段注释堪称是整篇文章最重要的说明,请大家始终记住这段信息,处处都用得上:
ObjectWaiter对象存在于WaitSet、EntryList、cxq等集合中,或者正在这些集合中移动
原文如下:
请务必记住这三个集合:WaitSet、EntryList、cxq
好了,接下来看源码分析问题吧:
线程A在wait()的时候做了什么
打开hotspot/src/share/vm/runtime/objectMonitor.cpp,看ObjectMonitor::wait方法:
如上图所示,有两处代码值得我们注意:
-
绿框中将当前线程包装成ObjectWaiter对象,并且状态为TS_WAIT,这里对应的是jstack看到的线程状态WAITING;
-
红框中调用了AddWaiter方法,跟进去看下:
这个ObjectWaiter对象被放入了WaitSet中,WaitSet是个环形双向链表(circular doubly linked list)
回到ObjectMonitor::wait方法接着往下看,会发现关键代码如下图,当前线程通过park()方法开始挂起(suspend):
至此,我们把wait()方法要做的事情就理清了:
-
包装成ObjectWaiter对象,状态为TS_WAIT;
-
ObjectWaiter对象被放入_WaitSet中;
-
当前线程挂起;
线程B持有锁的时候线程C在干啥
此时的线程C无法进入synchronized{}代码块,用jstack看应该是BLOCKED状态,如下图:
我们看看monitorenter指令对应的源码吧,位置:openjdk/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
#ifdef ASSERT
thread->last_