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

时间:2019-01-19 08:59:51

标签: java

我要问的是等待过程,而不是访问排序方法,它是最简单的形式,带有条件退出的无限循环。

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

3 个答案:

答案 0 :(得分:1)

Object.wait()功能是根据JVM_MonitorWait javadoc使用ThreadReference本机方法实现的:

/** Thread is waiting - Object.wait() or JVM_MonitorWait() was called */
public final int THREAD_STATUS_WAIT = 4;

该方法的实现可以在jvm.cpp中找到,并使用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实现在synchronizer.cpp中,并在objectMonitor.cpp中委托给ObjectMonitor::wait

如果继续进行挖掘,最终将达到依赖于平台的本机Java线程实现。在Linux上,它将是libpthread.so,它将最终处理线程状态更改。

答案 1 :(得分:1)

  

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

不,不是。那是低效的,不是通常的做法。

细节是复杂的并且与系统有关(请参阅@Karol的答案以获取代码链接),但一般方法如下。

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

  1. 将线程详细信息添加到互斥对象的“对象正在等待”队列中。
  2. 放弃线程的互斥锁。
  3. 通过告诉操作系统使其进入“休眠”状态。
  4. 操作系统发现了其他一些要调度的线程。如果不存在,它将导致内核进入低功耗的“空闲”循环或将其挂起。 (这取决于操作系统和硬件。)

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

  1. 它从互斥量队列中删除一个线程。
  2. 它告诉操作系统(先前)等待的线程应该被唤醒。
  3. 它从notify()调用返回,并(希望)释放互斥锁。

操作系统执行以下操作:

  1. 它找到一个免费的处理器来运行线程,然后启动。
  2. 如果没有可用的内核,则操作系统会将线程添加到可运行线程的调度程序队列中。
  3. 线程启动时,它首先尝试重新获取互斥锁...如果其他某个线程仍在保持该锁,则它可能会使其重新进入睡眠状态。
  4. 最后,wait调用返回,该线程通常会重新检查条件变量,然后释放锁。

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


  

等待请求的最耗资源的方法是什么,这使我不得不问这个问题。

最少消耗资源的方法是Object.waitObject.notify ...

答案 2 :(得分:0)

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

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