【发布时间】:2018-07-08 17:18:47
【问题描述】:
我试图了解 notify 如何唤醒一个线程并面临一些关于热点 (jdk8) 中的实现细节的误解。
我们在Object 中声明了wait/notify 作为本机方法,它们在此处实现:wait 和notify。由于static int Knob_MoveNotifyee = 2 ; 我预计the following code 负责执行唤醒:
if (Policy == 2) { // prepend to cxq
// prepend to cxq
if (List == NULL) {
iterator->_next = iterator->_prev = NULL ;
_EntryList = iterator ;
} else {
iterator->TState = ObjectWaiter::TS_CXQ ;
for (;;) {
ObjectWaiter * Front = _cxq ;
iterator->_next = Front ;
if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
break ;
}
}
}
}
但问题是 void ObjectWaiter::notify 方法被包装到 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify"); /Thread::SpinRelease (&_WaitSetLock) ; 中。
为什么我们在将等待队列中的出队线程预置到
cxq时会有 CAS?因为我们已经收购了_WaitSetLock,所以那里似乎没有争用。谁来修改
JavaThread状态?我们有iterator->wait_reenter_begin(this);at the end ofvoid ObjectWaiter::notify,但这不像wait_reenter_end中那样set_thread_status(java_thread, java_lang_Thread::RUNNABLE);
【问题讨论】:
-
1.我没有很好地阅读 C++,但我认为正在发生的事情是所有在监视器上阻塞的 Java 线程都存储在一个列表(队列)中。并且要对该列表进行操作需要互斥锁。这就是首先调用
_WaitSetLock的原因。所以这里有两个线程安全的概念。一个是针对正在被操作的线程列表,而第二个是针对我们正在操作的数据结构。 -
2.对于线程状态,我假设 JVM 使用线程的操作系统实现,并且操作系统直接设置这些线程的状态。
-
@markspace 2. 但是当
wait_reenter_begin被调用时,线程的状态被设置为BLOCKED_ON_MONITOR_ENTER显式here。但是当线程是 Runnable 时,它的状态是(显然?)RUNNABLE。我希望即使 JVM 使用操作系统线程,它也应该将状态设置为RUNNABLE无论如何,不是吗?
标签: java multithreading jvm jvm-hotspot