Делает ли Thread.yield () что-нибудь, если у нас достаточно процессоров для обслуживания всех потоков? - PullRequest
39 голосов
/ 08 мая 2019

Если мы находимся в ситуации с двумя запущенными потоками на машине с двумя процессорами, и мы вызываем Thread.yield() в одном из этих потоков, то понятно ли, что ничего не произойдет (планировщик по существу проигнорирует запрос), потому что у нас достаточно процессоров для обслуживания запущенных потоков?

Ответы [ 3 ]

26 голосов
/ 08 мая 2019

Всякий раз, когда поток вызывает метод Thread.yield(), он дает подсказку планировщику потока, что он готов приостановить выполнение.Планировщик потока может игнорировать эту подсказку.

Если какой-либо поток выполняет метод yield, планировщик потока проверяет, существует ли какой-либо выполняемый (ожидающий выполнения) поток с таким же или высоким приоритетом, чем у этого потока.Если процессор обнаружит какой-либо поток с более высоким или одинаковым приоритетом, он переключится на новый поток.Если нет, текущий поток продолжает выполняться.

Поскольку в вашем примере у вас достаточно процессоров для обслуживания всех потоков (они работают, не ожидая в состоянии выполнения);Thread.yield() ничего не сделает, и ваши потоки продолжат свое выполнение.

Примечание о Windows от Microsoft DOTNet:

Этот метод эквивалентениспользование вызова платформы для вызова собственной функции Win32 SwitchToThread .

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

, поэтому в некоторых ситуациях могут возникать ошибки.

13 голосов
/ 08 мая 2019

Thread.yield() устарел.Если ваша программа не будет работать на платформе, которая реализует кооперативную многозадачность или на JVM, которая все еще использует зеленые потоки , тогдабессмысленно называть его.

Стандартная библиотека Javadoc для Thread.yield() фактически говорит, что yield() вообще ничего не должен делать.

7 голосов
/ 09 мая 2019

Я всегда думал, что Thread::yield следует заменить на Thread::onSpinWait (начиная с java 9) - это всего лишь форма "более слабой" доходности, пока я не увидел использование обоих в StampedLock:

    else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
        Thread.yield();
    else
        Thread.onSpinWait();
    return 0L;

Так что я не думаю, что это устарело.Внутренне в источниках jdk он имеет много применений, даже относительно новый ForkJoinPool имеет использования Thread::yield.

На практике я использовал Thread::onSpinWait только внутри занятых спинов - потому что по крайней мере от названия этого - очень ясно, когда его использовать;с другой стороны, уступать - нет, поэтому я не могу точно сказать, когда и как его использовать.

Просто мои 0,02 $.

...