Является ли wait (1) в неблокирующем цикле while (true) более эффективным, чем использование wait () и notify ()?

Использует ли while(true) цикл Java вместе с wait(1) больше или меньше ресурсов, чем цикл блокировки с wait() и notify()?

И есть ли у ядер ЦП какие-то специальные (аппаратные) реализации, позволяющие wait(1)? Если да, то есть ли ограничения при работе с такими неблокирующими петлями?

Пример:

while(true){
    wait(1);
    //do the job here...
}

(Просто примечание: без wait(1) ядро ​​стало бы радикальным на 100% в while(true) цикле ...)


person Marcus    schedule 07.02.2014    source источник
comment
Что ж, wait(1) действительно подождите одну миллисекунду. Миллисекунда - это очень долгий промежуток времени с точки зрения тактовой частоты процесса ЦП, поэтому ЦП обычно отдыхает на целую миллисекунду каждые ... сколько бы времени ни потребовалось для обработки while(true).   -  person ryvantage    schedule 07.02.2014
comment
Вы проверили, как долго он на самом деле ждет? Это может быть около 20 мс, поскольку все это время как минимум зависит от ОС и от того, какую точность планирования она обеспечивает.   -  person zapl    schedule 07.02.2014
comment
Это правильно, в конце концов, все зависит от оборудования и ОС. Но это единственный выход. Я имею в виду: блокировка не будет быстрее, не так ли?   -  person Marcus    schedule 07.02.2014
comment
Вы не можете полностью заблокировать ядро ​​ЦП, планировщик потоков ОС по-прежнему будет выполнять свои собственные задачи (например, планирование потоков) с более высоким приоритетом, чем все, что вы делаете, даже без какого-либо wait (или лучше Thread.yield()). Ваш код является гостем, который может предоставлять подсказки системе, но он может остановить ваш поток, сохранить его контекст и продолжить позже в любой момент.   -  person zapl    schedule 07.02.2014
comment
Запустите столько потоков, сколько ваша машина может обработать, используя метод wait (1), а затем сравните с использованием метода ожидания (Integer.MAX_VALUE). Что ты видишь?   -  person Durandal    schedule 07.02.2014
comment
@zapl: Значит, вы имеете в виду, что wait(1) может использовать даже больше времени, чем просто wait() и notify()? Окей, ты меня понял, теперь мне действительно нужно это проверить. ;)   -  person Marcus    schedule 07.02.2014
comment
Я не знаю, как будет выглядеть цикл с ожиданием и уведомлением :) И я обычно не использую wait / notify, потому что в util.concurrent есть гораздо более приятные утилиты синхронизации и такие вещи, как блокировка очередей и многое другое, поэтому мне никогда не нужен цикл, который ждет.   -  person zapl    schedule 07.02.2014


Ответы (4)


Что касается исходного вопроса о том, почему while (true); занимает больше ЦП, чем while (true) { wait(1); }, подумайте: современный ЦП может выполнять миллиарды инструкций в секунду. При использовании цикла wait(1), если он идеален и каждый раз ожидает ровно одну миллисекунду, вы ограничиваете процессор до одной тысячи инструкций в секунду. Без него нет ограничений, и вместо этого он может выполнять замкнутый цикл миллиарды раз в секунду.

Что касается нового вопроса о том, что более эффективно, подход while (true) { wait(1); } против wait() и notify() рассмотрения ...

Допустим, вы ждете по условию. Вариант первый:

while (true) {
    wait(1);
    if (condition()) {
        break;
    }
}

vs.

wait();

и в другом месте:

//code which causes condition() to be true
notify();

Скажем, требуется 10 секунд, чтобы условие стало истинным. В первом подходе вы звоните wait(1) 10 000 раз и проверяете condition() 10 000 раз. Во втором подходе вы вызываете wait() один раз и notify() один раз.

person Claudiu    schedule 07.02.2014
comment
Не миллионы, миллиарды! - person ; 07.02.2014
comment
@waTeim: это же квадриллионы, не так ли? - person Claudiu; 07.02.2014
comment
Я немного изменил вопрос. Может быть, вы хотите улучшить свой ответ? - person Marcus; 07.02.2014
comment
@Marcus: Ну, конечно, будет более эффективно wait(), а затем получать уведомления при изменении условия, вместо того, чтобы делать wait(1) снова и снова и опрашивать условие. - person Claudiu; 07.02.2014
comment
Я также хочу указать, что wait(1) может быть медленнее, потому что notify() и wait() могут использовать НАМНОГО МЕНЬШЕ 1 миллисекунды ... - person Marcus; 07.02.2014
comment
@Marcus: Вам действительно нужно указать здесь вариант использования. - person Claudiu; 08.02.2014

Это вопрос с подвохом?

Когда вы помещаете «wait ()» в цикл, он освобождает переменную синхронизации, позволяя другому потоку двигаться вперед и в конечном итоге уведомлять этот поток о том, что он может продолжить. Поток не будет продолжен и не будет использовать циклы процессора, пока не получит это уведомление. И поэтому wait / notify необходимо вызывать из блоков или методов sync'd (не ясно, делаете ли вы это здесь).

Напротив, «while ... true» - это бесконечный цикл, который будет использовать каждый цикл процессора, который вы ему даете, до тех пор, пока не будет выполнено конечное условие.

Я рекомендую хорошую книгу по потокам Java и синхронизации, например https://rads.stackoverflow.com/amzn/click/com/0130170070

person Peter vdL    schedule 07.02.2014

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

Это станет особенно важным, если у вас работает много этих потоков, поскольку накладные расходы приходятся на поток.

person Tim B    schedule 07.02.2014
comment
Есть ли у вас какие-либо доказательства, тестовые примеры, что он использует больше ресурсов? Что ж, ясно, что блокирующий поток использует меньше ресурсов ЦП, но также больше времени ... поэтому я не уверен, что он использует больше ресурсов в конце концов (учитывая, что продолжительное время во время заполнения кеша также является пустой тратой и может использоваться для других потоков). - person Marcus; 07.02.2014

По сути, Клаудиу прав: процессоры действительно очень быстрые.

Но есть еще один фактор, который следует учитывать: на самом деле wait(1) всегда необходим в неблокирующих потоках, чтобы позволить другим потокам продолжить работу. Потому что, если ожидания вообще нет, ОС не может выделить ресурсы какому-либо другому потоку, и они будут голодать. С другой стороны, wait(1) может в действительности вызвать гораздо более длительное ожидание в зависимости от того, как ОС распределяет ресурсы. Но это зависит от ОС.

При программировании всегда нужно учитывать 2 фактора:

1. объем кеш-памяти / ОЗУ и

2. время, необходимое для потока / процесса.

Следовательно, все зависит от количества ресурсов, используемых ЗА ВРЕМЯ: МБ / с (или в целом: байтов / с). Вы не можете принимать правильные решения только на основе выделенных ресурсов, как намереваются делать многие программисты. Возможно даже, что вышеуказанный неблокирующий floop использует намного меньше ресурсов, чем блокирующий, потому что нет накладных расходов на синхронизацию. Так что никогда не забывайте о временном измерении.

Заключение. Более быстрые неблокирующие программы (могут) использовать меньше ресурсов.

person Marcus    schedule 07.02.2014
comment
Потому что, если ожидания вообще нет, ОС не может выделить ресурсы какому-либо другому потоку, и они будут голодать. Это не так. Ключевое слово здесь - упреждающее планирование, что в значительной степени является нормой для ОС общего назначения. Что происходит, так это то, что доступное время процессора распределяется равномерно (с учетом ограничений, таких как приоритет) между потоками, которые готовы к запуску. Конечно, отказ от использования времени процессора (через ожидание) действительно увеличивает часть времени процессора, выделенную для других потоков, потому что ожидающий поток отказывается от доли времени процессора, которую он получил бы во время работы. - person Durandal; 07.02.2014
comment
Окей, спасибо за подсказку. В конце концов, я уже не уверен, что использование wait(1) более эффективно, чем wait()и notify(). Если вы это знаете, смело пишите ответ, и я его приму. - person Marcus; 07.02.2014