Зависят ли накладные расходы на получение блокировки от разрешения таймера ОС при переключении контекста?

Предположим, поток 1 пытается получить блокировку объекта lockObj с помощью оператора lock(lockObj), но этот объект уже заблокирован потоком 2 в данный момент. поток 1 пытается заблокировать его. Поток 1 будет заблокирован, верно?

Теперь предположим, что во время этой блокировки происходит переключение контекста, потому что есть другие потоки и приложения, ожидающие запуска. Зависит ли время, прошедшее до тех пор, пока поток 1 снова не перейдет в состояние Работает и сможет получить блокировку, от разрешения таймера ОС (пример: 15,6 мс по умолчанию в Windows 7)?

Если ответ на поставленный выше вопрос ДА, то у меня есть еще одно сомнение:

Легко создать простую программу для проверки средних накладных расходов Thread.Sleep(1) с помощью секундомера и сделать вывод, что они сходятся к разрешению таймера ОС (например, 15,6 мс). Но мне трудно создать программу, чтобы получить такой же вывод для оператора lock. В основном потому, что:

1) Трудно гарантировать, что поток, пытающийся получить блокировку, всегда будет блокироваться (или, по крайней мере, знать, КОГДА он заблокировал, прежде чем получить блокировку);

2) Я не знаю, как принудительно переключить контекст всякий раз, когда поток пытается получить блоки блокировки. ВСЕГДА есть переключение контекста, когда текущий запущенный поток блокируется?

Любая помощь будет оценена по достоинству.


person Marcos Arruda    schedule 13.09.2014    source источник
comment
Нет, если бы это было так, потоки работали бы плохо. На таймеры влияет скорость, а не синхронизация.   -  person Hans Passant    schedule 13.09.2014
comment
Итак, в основном вы говорите, что, когда поток блокируется из-за того, что он ожидает получения блокировки, он не переносится на тестирование в следующем временном интервале ОС, чтобы проверить, была ли уже снята блокировка объекта. Существует еще один механизм, который заставляет блокирующий поток узнавать о снятии блокировки объекта, как только это происходит, и заставляет этот поток снова перейти в состояние Выполнение?   -  person Marcos Arruda    schedule 13.09.2014
comment
Просто все работает наоборот. Когда объект синхронизации освобождается, ОС проверяет, не ожидал ли его кто-нибудь. Если это так, этот поток разблокируется и его приоритет повышается. Достаточно часто, чтобы поток получил ядро.   -  person Hans Passant    schedule 13.09.2014


Ответы (1)


Предположим, поток 1 пытается получить блокировку объекта lockObj с помощью оператора lock (lockObj), но этот объект уже заблокирован потоком 2 в момент, когда поток 1 пытается заблокировать его. Поток 1 будет заблокирован, верно?

да.

Теперь предположим, что во время этой блокировки происходит переключение контекста, потому что есть другие потоки и приложения, ожидающие запуска. Зависит ли время, прошедшее до тех пор, пока поток 1 снова не перейдет в состояние «Работает» и сможет получить блокировку от разрешения таймера ОС (например, 15,6 мс по умолчанию в Windows 7)?

Не прямо, нет. Как правило, поток 1 становится готовым, как только объект ожидания, на котором он был заблокирован, получает сигнал. В ЭТО ВРЕМЯ будет запущен алгоритм планирования ОС, и поток 1 будет запущен на ядре, если оно свободно или если его приоритет достаточен для включения в набор потоков для запуска на доступных ядрах. Возможно, что таймер прерывает мое случайное прибытие и устанавливает готовый другой высокоприоритетный «поток 3» и, таким образом, предотвращает запуск потока 1, но это далеко не означает, что «получение блокировки зависит от разрешения таймера ОС» .

Если есть свободное ядро ​​для запуска потока 1, я эмпирически обнаружил, что он запускается через ~ 7 мкс после сигнала из потока 2 в моей системе Windows - через несколько микросекунд, а не 15,6 мс или что-то в этом роде.

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

Старайтесь не зацикливаться на концепции «квантов» (это глупое название, потому что «кванты» должны быть неделимыми, а потоки редко выполняются с точными интервалами, управляемыми таймером из-за ввода-вывода и межпотоковой передачи сигналов) и подумайте вместо конечного автомата, входами которого являются аппаратные прерывания и системные вызовы, а выходом - набор потоков, выполняемых на ядрах. Прерывание аппаратного таймера - лишь один из таких входов, которые могут изменить набор запущенных потоков.

person Martin James    schedule 14.09.2014