Как реализовано Java `wait ()` wait? [закрыто]

0
задан Karol Dowbecki 19 January 2019 в 10:07
поделиться

3 ответа

это в простейшей форме бесконечный цикл с условным выходом?

Нет, это не так. Это неэффективно, а не так, как это обычно делается.

Детали сложны и зависят от системы (см. Ответ @ Karol для ссылок на код), но общий подход заключается в следующем.

Когда поток вызывает wait(), метод выполняет следующее:

  1. Добавляет подробности потока в очередь объекта мьютекса «ожидающие объекты».
  2. Откажитесь от блокировки мьютекса потока.
  3. «Припаркуйте» ветку, сказав ОС, чтобы она усыпила.
  4. ОС находит какой-то другой поток для планирования. Если его нет, оно заставляет ядро ​​переходить в «маломощный» цикл или приостанавливает его или что-то в этом роде. (Это зависит от операционной системы и оборудования.)

Затем, когда другой поток вызывает notify, метод notify делает следующее:

  1. Он удаляет поток из мьютекса. очереди.
  2. Он сообщает ОС, что (ранее) ожидающий поток должен быть разбужен.
  3. Он возвращается из вызова notify() и (надеюсь) снимает блокировку мьютекса.

ОС делает следующее:

  1. Она находит свободный процессор для запуска потока и запускается.
  2. Если ни одно ядро ​​не свободно, ОС добавляет поток в очередь планировщика запускаемых потоков.
  3. Когда поток запускается, он сначала пытается повторно получить блокировку мьютекса ... что может привести к его возвращению в спящий режим, если какой-то другой поток все еще удерживает блокировку.
  4. Наконец, возвращается вызов wait, и поток обычно перепроверяет переменную условия, а затем снимает блокировку.

Дело в том, что (как правило) не существует бесконечных циклов, которые потребляют процессор, пока поток ожидает.


Какой наименее ресурсоемкий способ ожидания запроса, который заставил меня спросить об этом.

Наименее ресурсоемким способом будут Object.wait и Object.notify ...

0
ответ дан Stephen C 19 January 2019 в 10:07
поделиться

Object.wait() функциональность реализована с помощью JVM_MonitorWait нативного метода, согласно ThreadReference javadoc:

/** 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::wait в objectMonitor.cpp [ 1115].

Если вы продолжите копать, вы в конечном итоге достигнете нативной реализации потока Java, которая зависит от платформы. В Linux это будет libpthread.so, который в конечном итоге будет обрабатывать изменение статуса потока.

0
ответ дан Karol Dowbecki 19 January 2019 в 10:07
поделиться

В синхронном программировании монитор может рассматриваться как блок или, более конкретно, блок управления (для внесения каких-либо изменений в объект) с пространством только одного потока в любой данный момент. Таким образом, нескольким потокам можно запретить одновременную запись одного объекта и защиту объекта от повреждения. В нем метод wait () сообщает потоку, если какой-либо другой поток уже находится на мониторе, и, если это так, сообщает вызывающему потоку WAIT для выхода другого потока. Или, технически, сообщает вызывающему потоку SLEEP, пока не получит уведомление.

Он останавливает любое дальнейшее выполнение кода в вызывающем потоке, в отличие от бесконечного цикла, в котором выполнение продолжается, но никакого кода после цикла не выполняется, пока цикл не прервется.

0
ответ дан PranshuKhandal 19 January 2019 в 10:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: