对于Object wait操作的发现,同一个对象的wait操作被不同线程调用,synchronized不起作用。
public class SyncAndWait { private Object obj = new Object(); public static void main(String[] args) throws InterruptedException { SyncAndWait sync = new SyncAndWait(); new Thread(() -> {sync.sync();}).start(); new Thread(() -> {sync.sync();}).start(); Thread.sleep(5000); } public void sync() { synchronized (obj) { System.out.println("sync"); // try { // obj.wait(5000); // } catch (InterruptedException e) { // e.printStackTrace(); // } try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行上面代码,我们都知道两个sync相隔5s。 而如果去掉注释,sync就是接着输出的。这是为什么呢?
这里我们得要进入wait的native方法找答案了。
Object.c
static JNINativeMethod methods[] = { {"hashCode", "()I", (void *)&JVM_IHashCode}, {"wait", "(J)V", (void *)&JVM_MonitorWait}, {"notify", "()V", (void *)&JVM_MonitorNotify}, {"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll}, {"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone}, };
jvm.cpp
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
最主要的就是ObjectSynchronizer::wait,参见synchronizer.cpp,首先偏向锁校验,这里需要撤销偏向锁。接下来时间校验,以及释放当前持有的锁,并将线程加入到obj所属的条件队列,而后阻塞
synchronizer.cpp
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()); 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); }
参考资料:Wait-Notify机制
-----------------------------------------------如有错误请指正------------------------------