Primeiro: uma CPU não "tem" threads, apesar do que o marketing tenta reivindicar. Uma CPU pode ser executada até o número indicado de threads ao mesmo tempo. Especificamente, uma CPU com núcleos n e hyperthreading não ativados podem executar encadeamentos n . Uma CPU com núcleos n e hyperthreading ativado pode executar 2_n_ threads. Em contextos técnicos, nos referimos a "o que pode executar um thread" como um processador lógico , ou LP. Uma máquina sem HT habilitado tem um LP por núcleo; HT dá dois.
Um sistema Windows típico possui centenas grandes ou mesmo pequenos milhares de segmentos, totais, de uma só vez. Isso depende do código de cada programa individual para decidir. Quando você cria um processo, esse processo sempre começa com um thread. Alguns programas simples, particularmente programas de linha de comando (modo de caractere), podem usar apenas um thread. Mas o código em execução nesse primeiro segmento pode criar outros segmentos, e os esses segmentos podem criar outros segmentos, e assim por diante, quase sem um limite prático. Há boas razões para não simplesmente criar um grande número de threads, mas não há nada que torne impossível criar muito mais threads do que se poderia usar.
(No x86, com os valores padrão para o tamanho da pilha do encadeamento, há um limite de aproximadamente 2000 encadeamentos por processo - imposto pelo limite do espaço de endereço.)
Na guia Detalhes do Gerenciador de Tarefas, você pode ativar a coluna Threads, que informará quantos threads estão em cada processo no momento. Aqui está um comando do PowerShell que contará todos os segmentos em seu sistema:
($threads = get-ciminstance win32_thread).count
3437
Isto está em uma máquina com quatro núcleos hyperthreaded, total de oito LPs.
Isso não é um problema porque apenas alguns desses segmentos realmente querem ser executados a qualquer momento. A maioria dos threads na maioria dos processos passou a maior parte do tempo no que o Windows chama de estado de "espera", o que significa que eles não querem ou não podem usar o tempo de CPU no momento. Eles estão esperando por E / S (talvez rede, talvez disco, etc.) para completar, eles estão esperando por entrada do usuário, eles estão esperando por algum outro segmento para liberar um recurso que eles precisam acessar, etc. * Sistemas derivados de nix chamam isso de "bloqueado".)
Se você quiser o número de segmentos Aguardando, tente isto:
PS C:\Users\jeh> ($threads = get-ciminstance win32_thread | where-object -Property ThreadState -EQ 5).count
3427
Parece que há apenas 10 tópicos tentando usar os LPs no momento. Mas é ainda melhor que isso. Com 8 LPs, 8 desses encadeamentos são os encadeamentos inativos do sistema. Há um thread ocioso dedicado a cada LP. Eles estão sempre prontos para correr, mas eles só funcionam se nada mais quiser no LP. Então, no momento em que fiz os comandos acima, havia apenas dois threads "reais" que queriam fazer o trabalho. As atividades dos encadeamentos inativos não são incluídas nas exibições de gráfico de linha do Gerenciador de Tarefas de utilização da CPU.
n.b .: Esses números não são muito precisos porque essas operações do Powershell e do WMI não são sincronizadas internamente com as funções do sistema operacional. Mas eles são facilmente próximos o suficiente para ilustrar o ponto.
Se houver mais encadeamentos (além dos encadeamentos inativos) "Prontos" do que LPs, o agendador, em geral, selecionará os encadeamentos nLPs de maior prioridade - sujeito a alguns ajustes de acordo com quem correu em que CPUs recentemente. Se houver vários encadeamentos com a mesma prioridade, eles poderão ser "divididos em tempo", sendo executados de forma "round-robin", cada um podendo ser executado por 20 ou 60 ms antes que o agendador faça o switch LP para outro.
Aqui é uma resposta que eu dei, que entra em muito mais detalhes sobre como as prioridades de thread funcionam no Windows.