为了账号安全,请及时绑定邮箱和手机立即绑定

java `wait()` 等待是如何实现的?

java `wait()` 等待是如何实现的?

素胚勾勒不出你 2022-05-12 15:02:25
我问的是等待过程而不是访问排序方法,它是最简单的形式,是带有条件退出的无限循环。什么是等待请求的资源消耗最少的方式,这就是让我问这个的原因。
查看完整描述

3 回答

?
慕村225694

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,这将最终处理线程状态的变化。


查看完整回答
反对 回复 2022-05-12
?
暮色呼如

TA贡献1853条经验 获得超9个赞

最简单的形式是带条件退出的无限循环吗?

不,不是。这是低效的,而不是通常的做法。

细节很复杂并且取决于系统(请参阅@Karol 的代码链接的答案),但一般方法如下。

当线程调用wait()时,该方法执行以下操作:

  1. 将线程详细信息添加到互斥对象的“等待对象”队列中。

  2. 放弃线程的互斥锁。

  3. 通过告诉操作系统使其进入睡眠状态来“停放”线程。

  4. 操作系统找到一些其他线程来调度。如果没有,它会导致核心进入低功耗“空闲”循环或暂停它或其他东西。(这取决于操作系统和硬件。)

然后当另一个线程调用时notify, notify 方法执行以下操作:

  1. 它从互斥队列中删除一个线程。

  2. 它告诉操作系统应该唤醒(以前)等待的线程。

  3. 它从notify()调用中返回并(希望)释放互斥锁。

操作系统执行以下操作:

  1. 它找到一个空闲的处理器来运行线程,然后启动。

  2. 如果没有可用的内核,操作系统会将线程添加到调度程序的可运行线程队列中。

  3. 当线程启动时,它首先尝试重新获取互斥锁......如果其他线程仍然持有锁,这可能会导致它重新进入睡眠状态。

  4. 最后wait调用返回,线程通常会重新检查条件变量,然后释放锁。

关键是(通常)没有在线程等待时消耗 CPU 的无限循环。


什么是等待请求的资源消耗最少的方式,这就是让我问这个的原因。

Object.wait资源消耗最少的方式是Object.notify......


查看完整回答
反对 回复 2022-05-12
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

在同步编程中,监视器可以被假设为一个盒子,或者更具体地说是一个控制盒(用于对对象进行任何更改),在任何给定时刻只有一个线程的空间。因此,可以防止多个线程同时写入一个对象并保护对象不被损坏。在其中,wait() 方法告诉一个线程,如果任何其他线程已经在监视器中,如果是,则告诉调用线程等待其他线程出来。或者从技术上讲,告诉调用线程 SLEEP 直到收到通知。

它停止调用线程中代码的任何进一步执行,这与无限循环不同,在无限循环中,执行继续,但循环之后没有代码执行,直到循环中断。


查看完整回答
反对 回复 2022-05-12
  • 3 回答
  • 0 关注
  • 155 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信