Во-первых: ЦП не имеет «потоков», несмотря на то, что маркетинговая затея пытается претендовать. Процессор может работать до указанного количества потоков одновременно. В частности, процессор с n ядрами и не включенной гиперпоточностью может запускать n потоков. Процессор с n ядрами и включенной гиперпоточностью может запускать потоки 2_n_. В техническом контексте мы называем «вещь, которая может запустить поток» как логический процессор или LP. Машина без HT имеет один LP на ядро; HT дает это два.
Типичная система Windows содержит сотни или даже тысячи потоков, всего в ней одновременно. Это зависит от кода каждой отдельной программы. Когда вы создаете процесс, этот процесс всегда начинается с одного потока. Некоторые простые программы, особенно программы командной строки (символьный режим), могут использовать только один поток. Но код, выполняющийся в этом первом потоке, может создавать другие потоки, и эти потоки могут создавать другие потоки и т. Д. Практически без практического ограничения. Есть веские причины не просто создавать огромное количество потоков, но нет ничего, что сделало бы невозможным создание гораздо большего количества потоков, чем можно было бы использовать.
(На платформе x86 со значениями по умолчанию для размера стека потоков существует ограничение в 2000 потоков на процесс, налагаемое лимитом адресного пространства.)
На вкладке «Сведения» диспетчера задач можно включить столбец «Потоки», в котором будет указано количество потоков в каждом процессе на данный момент. Вот команда PowerShell, которая подсчитает все потоки в вашей системе:
($threads = get-ciminstance win32_thread).count 3437
Это на машине с четырьмя гиперзаходными ядрами, всего восемь LP.
Это не проблема, потому что очень немногие из этих потоков действительно хотят работать в любой момент. Большинство потоков в большинстве процессов проводят большую часть своего времени в том, что Windows называет состоянием «ожидания», то есть они не хотят или не могут использовать процессорное время вообще. Они ожидают завершения ввода-вывода (может быть, сети, диска и т. Д.), Ожидают ввода данных пользователем, ожидают, что какой-то другой поток освободит ресурс, к которому им нужен доступ и т. Д. ( * Производные от nix системы называют это "заблокированным".)
Если вы хотите количество ожидающих потоков, попробуйте это:
PS C:\Users\jeh> ($threads = get-ciminstance win32_thread | where-object -Property ThreadState -EQ 5).count 3427
Похоже, что сейчас только 10 потоков пытаются использовать LP. Но это даже лучше, чем это. При 8 LP 8 из этих потоков являются простоями системы. Есть свободная тема, посвященная каждому LP. Они всегда готовы к запуску, но они запускаются только в том случае, если ничего не хочет LP. Поэтому в тот момент, когда я выполнял приведенные выше команды, было только два «настоящих» потока, которые хотели работать. Действия незанятых потоков не включены в линейный график диспетчера задач, показывающий загрузку ЦП.
Примечание: эти цифры не совсем точны, потому что эти операции Powershell и WMI не синхронизированы с функциями операционной системы. Но они легко достаточно близки, чтобы проиллюстрировать это.
Если потоков (кроме незанятых потоков) больше «Готово», чем существующих LP, то планировщик, как правило, выбирает потоки nLP с наивысшим приоритетом - с некоторыми изменениями в зависимости от того, кто недавно работал на каких процессорах. Если есть несколько потоков с одинаковым приоритетом, они могут быть «разделены по времени», работать в режиме «циклического перебора», каждый из которых может работать за 20 или 60 мсек, прежде чем планировщик выполнит переключение LP на другой.
Вот ответ, который я дал, в котором более подробно рассказывается о том, как работают приоритеты потоков в Windows.