3 回答
TA贡献1880条经验 获得超4个赞
Object.wait()JVM_MonitorWait根据ThreadReferencejavadoc ,功能是使用本机方法实现的:
/** Thread is waiting - Object.wait() or JVM_MonitorWait() was called */
public final int THREAD_STATUS_WAIT = 4;
该方法的实现可以在jvm.cppand uses中找到ObjectSynchronizer::wait:
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实现是 insynchronizer.cpp并委托给ObjectMonitor::waitin objectMonitor.cpp。
如果您继续深入研究,您最终将获得依赖于平台的本机 Java 线程实现。在 Linux 上libpthread.so,这将最终处理线程状态的变化。
TA贡献1853条经验 获得超9个赞
最简单的形式是带条件退出的无限循环吗?
不,不是。这是低效的,而不是通常的做法。
细节很复杂并且取决于系统(请参阅@Karol 的代码链接的答案),但一般方法如下。
当线程调用wait()
时,该方法执行以下操作:
将线程详细信息添加到互斥对象的“等待对象”队列中。
放弃线程的互斥锁。
通过告诉操作系统使其进入睡眠状态来“停放”线程。
操作系统找到一些其他线程来调度。如果没有,它会导致核心进入低功耗“空闲”循环或暂停它或其他东西。(这取决于操作系统和硬件。)
然后当另一个线程调用时notify
, notify 方法执行以下操作:
它从互斥队列中删除一个线程。
它告诉操作系统应该唤醒(以前)等待的线程。
它从
notify()
调用中返回并(希望)释放互斥锁。
操作系统执行以下操作:
它找到一个空闲的处理器来运行线程,然后启动。
如果没有可用的内核,操作系统会将线程添加到调度程序的可运行线程队列中。
当线程启动时,它首先尝试重新获取互斥锁......如果其他线程仍然持有锁,这可能会导致它重新进入睡眠状态。
最后
wait
调用返回,线程通常会重新检查条件变量,然后释放锁。
关键是(通常)没有在线程等待时消耗 CPU 的无限循环。
什么是等待请求的资源消耗最少的方式,这就是让我问这个的原因。
Object.wait
资源消耗最少的方式是Object.notify
......
TA贡献1858条经验 获得超8个赞
在同步编程中,监视器可以被假设为一个盒子,或者更具体地说是一个控制盒(用于对对象进行任何更改),在任何给定时刻只有一个线程的空间。因此,可以防止多个线程同时写入一个对象并保护对象不被损坏。在其中,wait() 方法告诉一个线程,如果任何其他线程已经在监视器中,如果是,则告诉调用线程等待其他线程出来。或者从技术上讲,告诉调用线程 SLEEP 直到收到通知。
它停止调用线程中代码的任何进一步执行,这与无限循环不同,在无限循环中,执行继续,但循环之后没有代码执行,直到循环中断。
添加回答
举报