park/unpark操作
这两个操作通常配合在一起使用,park操作用于阻塞当前线程,unpark用于使阻塞在park操作代码处的线程退出阻塞。
park操作
该方法是一个native方法:
public native void park(boolean isAbsolute, long time); |
该方法实现unsafe.cpp在\hotspot\src\share\vm\prims目录下。
UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) UnsafeWrapper("Unsafe_Park"); #ifndef USDT2 HS_DTRACE_PROBE3(hotspot, thread__park__begin, thread->parker(), (int) isAbsolute, time); #else /* USDT2 */ HOTSPOT_THREAD_PARK_BEGIN( (uintptr_t) thread->parker(), (int) isAbsolute, time); #endif /* USDT2 */ JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__park__end, thread->parker()); #else /* USDT2 */ HOTSPOT_THREAD_PARK_END( (uintptr_t) thread->parker()); #endif /* USDT2 */ UNSAFE_END |
以上代码需要展开来才能看得懂,展开后代码如下:
如果定义了USDT2宏
extern "C" { void JNICALL Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time) { JavaThread* thread=JavaThread::thread_from_jni_environment(env); ThreadInVMfromNative __tiv(thread);
/* do nothing */
HandleMarkCleaner __hm(thread); Thread* THREAD = thread;
/* begin of body */
/*nothing, for the present*/;
; JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); ; } } |
如果没有定义USDT2宏
这里不展开USDT2宏没有定义的那段代码 |
其中主要的代码在:
thread->parker()->park(isAbsolute != 0, time); |
这块代码实现在os_solaris.cpp,在\hotspot\src\os\solaris\vm目录下。
void Parker::park(bool isAbsolute, jlong time) {
// Optional fast-path check: // Return immediately if a permit is available. if (_counter > 0) { _counter = 0 ; OrderAccess::fence(); return ; }
// Optional fast-exit: Check interrupt before trying to wait Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); JavaThread *jt = (JavaThread *)thread; if (Thread::is_interrupted(thread, false)) { return; }
// First, demultiplex/decode time arguments timespec absTime; if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all return; } if (time > 0) { // Warning: this code might be exposed to the old Solaris time // round-down bugs. Grep "roundingFix" for details. unpackTime(&absTime, isAbsolute, time); }
// Enter safepoint region // Beware of deadlocks such as 6317397. // The per-thread Parker:: _mutex is a classic leaf-lock. // In particular a thread must never block on the Threads_lock while // holding the Parker:: mutex. If safepoints are pending both the // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock. ThreadBlockInVM tbivm(jt);
// Don't wait if cannot get lock since interference arises from // unblocking. Also. check interrupt before trying wait if (Thread::is_interrupted(thread, false) || os::Solaris::mutex_trylock(_mutex) != 0) { return; }
int status ;
if (_counter > 0) { // no wait needed _counter = 0; status = os::Solaris::mutex_unlock(_mutex); assert (status == 0, "invariant") ; OrderAccess::fence(); return; }
#ifdef ASSERT // Don't catch signals while blocked; let the running threads have the signals. // (This allows a debugger to break into the running thread.) sigset_t oldsigs; sigset_t* allowdebug_blocked = os::Solaris::allowdebug_blocked_signals(); thr_sigsetmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); #endif
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); jt->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
// Do this the hard way by blocking ... // See http://monaco.sfbay/detail.jsf?cr=5094058. // TODO-FIXME: for Solaris SPARC set fprs.FEF=0 prior to parking. // Only for SPARC >= V8PlusA #if defined(__sparc) && defined(COMPILER2) if (ClearFPUAtPark) { _mark_fpu_nosave() ; } #endif
if (time == 0) { status = os::Solaris::cond_wait (_cond, _mutex) ; } else { status = os::Solaris::cond_timedwait (_cond, _mutex, &absTime); } // Note that an untimed cond_wait() can sometimes return ETIME on older // versions of the Solaris. assert_status(status == 0 || status == EINTR || status == ETIME || status == ETIMEDOUT, status, "cond_timedwait");
#ifdef ASSERT thr_sigsetmask(SIG_SETMASK, &oldsigs, NULL); #endif _counter = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock") ;
// If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } OrderAccess::fence(); } |