共计 1630 个字符,预计需要花费 5 分钟才能阅读完成。
Object wait 和 notify 的实现机制
Java Object 类提供了一个基于 native 实现的 wait 和 notify 线程间通信的形式,这是除了 synchronized 之外的另外一块独立的并发根底局部,无关 wait 和 notify·的局部内容,咱们在下面剖析 monitor 的 exit 的时候曾经有一些波及,然而并没有过多的深刻,留下了不少的疑难,本大节会详细分析。
wait 实现
ObjectMonitor 类中的 wait 函数代码实现如下:
void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
...
if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
...
// 抛出异样,不会间接进入期待 THROW(vmSymbols::java_lang_InterruptedException());
...
}
...
ObjectWaiter node(Self);
node.TState = ObjectWaiter::TS_WAIT;
Self->_ParkEvent->reset();
OrderAccess::fence();
Thread::SpinAcquire(&_WaitSetLock, "WaitSet - add");
AddWaiter(&node);
Thread::SpinRelease(&_WaitSetLock);
if ((SyncFlags & 4) == 0) {_Responsible = NULL;}
...
// exit the monitor exit(true, Self);
...
if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {// Intentionally empty} else if (node._notified == 0) {if (millis <= 0) {Self->_ParkEvent->park();
} else {ret = Self->_ParkEvent->park(millis);
}
}
// 被 notify 唤醒之后的善后逻辑 ...
}
照例只列出 wait 函数的外围性能局部,首先会判断一下以后线程是否为可中断并且是否曾经被中断,如果是的话会间接抛出 InterruptedException 异样,而不会进入 wait 期待,否则的话,就须要执行上面的期待过程,首先会依据 Self 以后线程新建一个 ObjectWaiter 对象节点,这个对象咱们在后面剖析 monitor 的 enter 的视乎就曾经见过了。生成一个新的节点之后就是须要将这个节点放到期待队列中,通过调用 AddWaiter 函数实现 node 的入队操作,不过在入队操作之前须要取得互斥锁以保障并发平安:
void Thread::SpinAcquire(volatile int * adr, const char * LockName) {if (Atomic::cmpxchg (1, adr, 0) == 0) {return; // normal fast-path return}
// Slow-path : We've encountered contention -- Spin/Yield/Block strategy. TEVENT(SpinAcquire - ctx);
int ctr = 0;
int Yields = 0;
for (;;) {while (*adr != 0) {
++ctr;
if ((ctr & 0xFFF) == 0 || !os::is_MP()) {if (Yields > 5) {os::naked_short_sleep(1);
} else {os::naked_yield();
++Yields;
}
} else {SpinPause();
}
}
if (Atomic::cmpxchg(1, adr, 0) == 0) return;
}
}
正文完