Preface
Object wait/notify method is a thread synchronization method based on Object Monitor provided by early JVM. This paper first introduces the related data structures (classes), then starts with the internal implementation of wait/notify method, and briefly analyses the principle and implementation of Object Monitor.
Park
PlatformParker
ObjectMonitor
ObjectSynchronizer
wait
Many methods in Object class are native methods, wait is no exception.
public final void wait() throws InterruptedException { wait(0); } public final native void wait(long timeout) throws InterruptedException;
The corresponding native function of wait method is JVM_MonitorWait
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) JVMWrapper("JVM_MonitorWait"); Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); JavaThreadInObjectWaitState jtiows(thread, ms != 0); if (JvmtiExport::should_post_monitor_wait()) { JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); // The current thread already owns the monitor and it has not yet // been added to the wait queue so the current thread cannot be // made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT // event handler cannot accidentally consume an unpark() meant for // the ParkEvent associated with this ObjectMonitor. } ObjectSynchronizer::wait(obj, ms, CHECK); JVM_END
It first calls the JNIHandles::resolve_non_null function to convert the handle of job type into oop (refer to the previous series of articles on oop and Handle concepts), then calls the static method wait of the ObjectSynchronizer class, where the first class, ObjectSynchronizer, related to Object Monitor, appears, first marks it, and then looks down.
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { TEVENT(wait - throw IAX); THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_wait); DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis); monitor->wait(millis, true, THREAD); // This dummy call is in place to get around dtrace bug 6254741. Once // that's fixed we can uncomment the following line, remove the call // and change this function back into a "void" func. // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD); return dtrace_waited_probe(monitor, obj, THREAD); }
Here comes the second class ObjectMonitor (protagonist), which calls the wait method of monitor after obtaining the ObjectMonitor of the object through the ObjectSynchronizer::inflate method.