разрешение сна потока Java и ожидание синхронизированных блоков

Я хотел бы узнать больше о том, как работает разрешение сна потока и с чем оно связано, помимо разрешения sleep ().

Я знаю, что это определяется операционной системой, а в Windows обычно 15 мс. Мне не удалось подтвердить это, недавно осмотревшись, но я смутно припоминаю, что эти 15 мс зацикливаются ОС и являются `` глобальными '' для всех потоков, что означает, что вместо 15 мс, которые являются минимальным временем, в течение которого поток может спать, это скорее максимум сна (1). Это правильно? Одинаково ли это для всех операционных систем (по истечении срока действия)?

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

В синхронизированном блоке ожидающие потоки эффективно спят (1), проверяя блокировку в каждом цикле, или поток, выходящий из блока, мгновенно пробуждает ожидающий поток? Это одинаково для всех операционных систем?

Когда поток notify () - ed после wait (), будет ли он обрабатываться так же, как указано выше, пока он ожидает блокировки, или иначе?

Есть ли другой случай, когда цикл 15 мс имеет значение с точки зрения производительности?


person Numeron    schedule 19.06.2012    source источник


Ответы (2)


Вам нужно провести небольшое исследование многопоточных ядер.

'всегда ли будет происходить ложное пробуждение потока в точке действия этого цикла сна, или это может произойти в любое время?'

В Windows нет ложных пробуждений с помощью функции sleep () или какого-либо ожидания синхронизирующего объекта ядра - вообще нет. Любая такая тенденция была разработана в ядре и не распространяется на пользовательские потоки.

Если поток спит или ожидает какого-либо объекта синхронизации, такого как мьютекс или блокировка семафора, он вообще не запускается - это просто мертвый объект дескриптора потока в очереди в ядре и, следовательно, все связанные с потоком вещи, данные пространство для стека и т. д. В случае ожидания TDO находится в «дельта-очереди» всех потоков с тайм-аутом, упорядоченных по времени пробуждения, и ОС проверяет элемент в начале этой очереди каждые 15 мс. В случае ожидания блокировки по времени TDO находится в двух очередях - очереди с тайм-аутом и очереди, принадлежащей блокировке. Либо TDO достигнет заголовка очереди таймера и станет готовым, когда его интервал истечет, либо другой поток снимет блокировку и сделает поток готовым. Выигрывает тот, кто придет первым, и TDO удаляется из другой очереди. Затем вновь готовый поток присоединяется к набору готовых потоков, и, если ядро ​​доступно или поток с более низким приоритетом может быть вытеснен, новый готовый поток отправляется в ядро.

Таким образом, «15 мс» в Windows «разделяются» всеми потоками. Windows - это операционная система для настольных ПК, и 15 мс за пределами человеческого восприятия, поэтому 99,9% всех домашних потоков не заботятся, потому что им нужны только большие тайм-ауты, они ждут ввода-вывода, ждут какой-то блокировки межпотоковой связи или какой-либо комбинации из них.

«Есть ли другой случай, когда цикл 15 мс имеет значение с точки зрения производительности?»

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

person Martin James    schedule 19.06.2012
comment
Спасибо, это многое проясняет. Я должен отметить, что еще одно распространенное использование sleep () - разорвать цикл занятости, чтобы не расплавить ваш процессор. 15 мс в этом случае означает, что цикл будет выполняться только ~ 66 раз в секунду, что может вызвать заметную разницу в зависимости от приложения. - person Numeron; 20.06.2012
comment
@Numeron - вам нужен вентилятор / радиатор побольше. Нет, правда - все коробки, которые я использовал, могут разрядиться. Я слышу, как скорость вращения вентилятора увеличивается при полной загрузке всех ядер процессора, но ничего плохого не происходит. - person Martin James; 20.06.2012
comment
Настольные компьютеры - это нормально, но на ноутбуках это может стать серьезной проблемой. - person Numeron; 20.06.2012

Thread.sleep() реализация зависит от ОС.

Гранулярность ожидания обычно ограничивается периодом прерывания планировщика потоков. В Linux этот период прерывания обычно составляет 1 мс в последних ядрах (начиная с версии 2.6.8). В Windows период прерывания планировщика обычно составляет около 10 или 15 миллисекунд (что, как я считаю, определяется процессором), но более высокий период может быть запрошен в программном обеспечении, и JVM Hotspot делает это, когда считает необходимым.

person amicngh    schedule 19.06.2012
comment
Когда вы говорите, что это зависит от ОС, какие именно части вы имеете в виду? Просто период тайм-аута или больше? Вы также имеете в виду разницу между уникальным 10-15 мс на поток и общим циклом 10-15 мс? Зависит ли поток, ожидающий блокировок, от ОС? - person Numeron; 19.06.2012