Что произойдет, когда вставить `Thread.yield ()` в синхронизированную функцию - PullRequest
0 голосов
/ 04 июня 2018

Я изучаю многопоточность в Java.Ниже приведен демонстрационный код, и мне любопытно использовать Thread.yield() внутри функции.

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

Демонстрационный код:

public class SynchronizeEvenGenerator {
private int currentEvenValue = 0;
/**
 * Generate even and return it
 * @return
 */
public synchronized int next() {
    ++currentEvenValue;
    Thread.yield();
    ++currentEvenValue;
    return currentEvenValue;
    }
}

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Что произойдет, если Thread.yield() вызывается в синхронизированной функции?

Как javadoc для Thread.yield() состояний:

"[Это] подсказка планировщику о том, что текущий поток готов отдать свое текущее использование процессора. Планировщик может игнорировать эту подсказку."

Так что естьдве возможности:

  1. Ничего не происходит;т. е. вызов yield() немедленно возвращается.
  2. Запланирован другой поток, и он начинает выполняться.В конце концов, этот поток перенесен, и вызов yield() возвращается.

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


Разве это не синхронизированный метод, который не может быть вызван, пока не будет запущензадача заканчивает свою работу над этим?

Thread.yield не является синхронизированным методом.(И даже если бы это было так, это заблокировало бы объект Thread, а не блокировку, которую сейчас удерживает блок synchronized.)


Итак, в вашем примере, вызов next() гарантированно увеличивает счетчик ровно на 2. Если какой-то другой поток вызывает метод next(), второй вызов останется заблокированным до (по крайней мере) после возврата первого вызова.

Javadoc также говоритthis:

«Этот метод редко подходит для использования.»


Другой вопрос: станет ли он тупиком для планирования потоков

Нет.Поток, вызвавший yield(), будет в конечном итоге перенесен.

(Deadlock - это очень специфическое явление (см. статья в Википедии ), которое может происходить только при получении блокировки. Когда поток возвращает, он не получает и не снимает блокировки, поэтому он не может вызватьтупик.)

Теперь, когда поток возвращается, может пройти много времени, прежде чем он снова будет запланирован, особенно если есть много других выполняемых потоков с тем же приоритетом или более высоким .,Конечным результатом является то, что другие потоки, ожидающие получения блокировки, могут долго удерживаться.Это может чрезмерно увеличить споры и заторы.Но в конце концов, вызов yield() вернется, вызов next() вернется, и другой поток сможет получить блокировку.

Короче: вызов yield() при удержании блокировки ухудшает производительность, но это не приведет к тупику.

Как говорит Javadoc, звонить по номеру yield() редко бывает уместно.

0 голосов
/ 04 июня 2018

Разве это не синхронизированная функция, которая не может быть вызвана до тех пор, пока запущенная задача не закончит свою работу над ней?

Она не может быть запущена в другом потоке для того же объекта.

Тогда какая разница между вставкой Thread.yield () в этот блок, а не?

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

Если ожидающий поток не запущен, он замедлится примерно на 15-30 микросекунд.

cf wait (0), который может позволить другому потоку получить блокировку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...