Цитата |
---|
Юрий написал: соответственно при занятости всех ядер, получается что все эти операции становятся в очередь и вот вопрос как обрабатывается эта очередь? Не может ли случиться ситуации при которой последний в очереди поток вынужден будет ожидать обработки процессором своего события дольше чем того требуется из-за скопившейся очереди? Или все работает не так и я чегото не понимаю ? |
Это вопросы не про квик, а про ядро винды.
Пусть есть сколько-то потоков в системе. Для ядра они все одинаковые, оно не смотрит, это поток из квика или из браузера или еще откуда-то. Часть потоков спит или ждет какого-то события (спит это на самом деле тоже ждет события - таймера), они за процессор в данный момент не соревнуются. Другая часть готова к исполнению, и их (всегда) куда больше, чем ядер. У каждого потока есть некий приоритет, назначаемый при его старте. В ядре винды 32 очереди готовых потоков, по одной на каждый приоритет (которых тоже 32 всего). Каждые 16 мс происходит прерывание таймера, через каждые 2 прерывания очередной поток с ядра снимается и выбирается следующий поток на выполнение. Это будет первый поток из очереди с наивысшим приоритетом. Если высокоприоритетные очереди пусты, проверяются очереди с более низким приоритетом и т.д. С самым низким приоритетом выполняется поток idle, если дело до него дошло, он всякую там приборку фоновую выполняет и, если по-прежнему делать нечего, вырубает ядро, на котором работает. Потом оно запускается следующим прерыванием таймера, опять проверяются очереди, выполняются самые приоритетные потоки, потом потоки похуже, потом готовые потоки кончились, выполнился idle и ядро опять в спячку ушло. Кстати говоря, та "загрузка процессора", что вы видите в диспетчере задач, это по сути сколько процентов времени ядро работало (остальное время оно было выключено).
Поток, получивший ядро, может слететь с него двумя способами. Первый - это он решил чего-то подождать, т.е. перешел в состояние "не готов" и был снят с ядра, вместо него по обычному алгоритму выбран поток из самой приоритетной очереди. Второй - он отработал два кванта времени без ожиданий, тогда его принудительно сняла винда на очередном прерывании, поставила в хвост очереди для его приоритета и выбрала новый поток опять по тому же алгоритму. Теперь, пока все потоки, что стояли за снятым в очереди, не пройдут по кругу, до него дело не дойдет.
Если какой-то готовый поток слишком долго не получал ядра, винда ему временно повышает приоритет, чтобы тоже имел шанс поработать даже при большой загрузке ядер высокоприоритетными потоками. Также она повышает приоритет потоку, чье окно сейчас имеет фокус, чтобы окна были поотзывчивей. Потоки для работы с мультимедиа обычно уже создаются с высоким приоритетом. Остальные создаются с одинаковым приоритетом, поэтому грубо можно считать, что очередь одна для большинства потоков и они крутятся в ней по кругу, некоторые выпадают в спячку, некоторые наоборот выходят из спячки и в эту очередь встают, некоторые уходят рангом выше временно. Такой вот там круговорот жизни происходит.
В свете сказанного, как может быть, что поток будет ожидать дольше, чем требуется? Придет его очередь - попадет на ядро, сделает сколько успеет и встанет ждать следующего раза. Чем больше потоков, тем длиннее очередь, тем реже поток будет на ядро попадать, с какого-то момента это станет и визуально заметно в виде подлагивания (но не раньше, чем все ядра загрузятся на 100% и заревет вентилятор). Как писал выше, при 1000 потоков на процесс вы этого еще не очень-то заметите, если код написан нормально.