O Gerenciador de tarefas está dizendo que o sistema está executando com mais de mil threads


17

Abri o Gerenciador de tarefas e procurei na área "Sistema" e vi:

Tópicos: 1337

Como tenho um processador de núcleo duplo com hiperencadeamento disponível (ou seja, quatro threads), como é possível ter mais de 1000 threads quando meu processador deve ter apenas quatro?


3
Não é por isso que eles chamam de hiper -Threading? :)
um CVn 05/07

9
Puxa, eles finalmente inventaram a "multiprogramação" ??? (Este é 1967, certo?)
Daniel R Hicks

10
Alguém acabou de mudar o número para 1337?
Erty Seidohl

11
Como uma empresa com quatro mesas pode ter 1337 funcionários? Fácil; os funcionários se revezam nas mesas.
Eric Lippert

Respostas:


50

A resposta simples é que nem todos os threads estão executando simultaneamente. Para uma explicação mais completa, continue a ler.

O agendador de tarefas do sistema operacional geralmente pensa em agendar aplicativos, e isso permite que você execute uma tarefa enquanto o computador está trabalhando em outra. Antigamente, o teste decisivo da multitarefa formatava um disquete enquanto fazia outra coisa. Se você realmente deseja testar o sistema operacional, formate um disquete enquanto baixa um arquivo em um modem conectado à porta serial. À medida que o hardware se tornou poderoso o suficiente para realmente fazê-lo de maneira significativa, a reprodução de vídeo às vezes também aparece nesses testes. Se o agendador de tarefas do sistema operacional puder executar essas tarefas sem problemas, poderá lidar com qualquer coisa.

No entanto, o agendador de tarefas não agenda aplicativos (processos), ele agenda os encadeamentos . Cada aplicativo possui pelo menos um encadeamento, mas pode potencialmente usar um grande número de encadeamentos para dividir o trabalho realizado em partes relacionadas ou independentes. Por exemplo, é comum que um aplicativo tenha um encadeamento que lida com a interface do usuário e crie outro encadeamento quando o usuário iniciar uma operação potencialmente demorada (que pode ser algo como impressão, recalculando uma planilha, um ambiente de desenvolvimento executando uma pesquisa de símbolo, etc. etc.). Alguns ambientes de programação introduzem uma quantidade invisível de threads para o programador; por exemplo, Java e .NET podem fazer coleta de lixoem um thread separado, que está fora do controle imediato do programador. Alguns programas criam vários threads no início e os agrupam, porque a criação de novos threads é uma operação comparativamente cara (portanto, você não necessariamente precisa criar um thread toda vez que precisar de um). Qualquer coisa que faça uma visualização geralmente é feita em um encadeamento separado; portanto, o restante da interface do usuário permanece responsivo enquanto a visualização está sendo gerada. E assim por diante. Tomados em conjunto, tudo isso significa que o número de threads no sistema a qualquer momento pode facilmente ser muitas vezes o número de processos.

Cada thread pode estar em um dos poucos estados possíveis, mas a distinção mais importante é entre running , executável e espera estados; a terminologia pode diferir um pouco, mas essa é a ideia geral. A qualquer momento, apenas um encadeamento por virtual (devido ao hyperthreading e tecnologias similares) pode estar em execução no núcleo da CPU (ou seja, executando instruções de código de máquina), mas qualquer número de encadeamentos pode ser executável (o que significa que é um candidato a obter a CPU na próxima vez que o planejador precisar tomar uma decisão sobre qual thread deve ser permitido executar). Esperando (também conhecido como bloqueado) os threads aguardam por algo - os casos mais comuns provavelmente são os de espera de E / S de usuário, disco ou rede (a entrada do usuário em particular é excepcionalmente lenta).

A contagem de threads que você vê no gerenciador de tarefas é o número total de threads em qualquer um desses estados. Por exemplo, o sistema Windows 7 em que estou digitando isso atualmente tem cerca de 70 processos iniciados, mas quase 900 threads. Com todos os processos em segundo plano para lidar com várias tarefas e como elas provavelmente são subdivididas em uma infinidade de threads cada, esse não é um número escandaloso.

Indo um pouco mais a fundo na implementação técnica, no cerne do agendador de tarefas de um sistema operacional de multitarefas preventivas é geralmente algum tipo de gancho de interrupção de hardware. Isso significa que o kernel pode interromper a CPU quando não possui trabalho útil para executar (esse é quase certamente um dos motivos, se não o motivo, pelo qual o Linux verifica as HLTinstruções de inicialização no IA-32CPUs compatíveis e provavelmente faz verificações semelhantes em outras arquiteturas), com o conhecimento de que, em algum tempo futuro razoavelmente determinado, uma interrupção será acionada e o agendador de tarefas será chamado. Como a interrupção é acionada, independentemente de qual outro trabalho a CPU está executando (essa é a idéia por trás das interrupções), o agendador é executado regularmente e tem a chance de determinar qual thread deve ser executado durante o intervalo de tempo a seguir. Como as alternâncias de contexto são relativamente caras, geralmente é possível (pelo menos através do código-fonte) ajustar o quão agressivamente o agendador alterna entre threads; alternar encadeamentos com mais frequência faz com que o sistema se torne mais responsivo, mas a sobrecarga de comutação significa que o tempo total para concluir um determinado conjunto de tarefas é mais longo. O mais rápidoO sistema será aquele que alterna entre os threads apenas quando o thread em execução não puder mais ser executado (o que significa que ele fica bloqueado aguardando algo ou concluiu seu trabalho) porque isso minimiza a sobrecarga, enquanto o sistema mais responsivo alterna entre os threads toda vez que o agendador é chamado, porque isso minimiza o tempo médio de espera antes que um determinado segmento obtenha tempo de CPU. A configuração ideal geralmente está entre as duas, e a troca entre essas opções é provavelmente uma das principais razões pelas quais o Linux oferece vários agendadores para escolher, além de alguns parâmetros de ajuste na configuração do kernel.

Os sistemas operacionais e ambientes multitarefa cooperativamente, por outro lado (o Windows 3.x é um exemplo), dependem de cada aplicativo para ceder regularmente o controle ao agendador. Geralmente, existe uma função da API especificamente destinada a fazer isso, e muitas vezes muitas funções da API fazem isso como parte de seu fluxo de execução interno, porque ajuda a tornar a experiência do usuário mais suave. Essa abordagem de design funciona bem desde que todos os aplicativos sejam bem comportados e cedam o controle com intervalos curtos durante qualquer operação de longa duração (longa duração significa mais do que uma pequena fração de segundo), mas um aplicativo que não pode entupir todo o sistema. Esse é um grande motivo pelo qual o Windows 3.x se saiu tão mal no teste de multitarefa que mencionei acima, enquanto o OS / 2passeavam alegremente enquanto realizavam as mesmas tarefas no mesmo hardware: um aplicativo poderia instruir a unidade de disquete a gravar um determinado setor, e o tempo necessário para fazer isso antes que a chamada retornasse pudesse ser mensurável (dezenas a centenas de milissegundos ou Mais); um sistema multitarefa preventivamente interromperia o agendador na próxima chamada agendada, observe que o encadeamento atualmente "em execução" está realmente bloqueado pela chamada de gravação e simplesmente mude para outro encadeamento executável. (Na prática, é um pouco mais envolvido, mas essa é a ideia geral.)

Nos ambientes preventivamente multitarefa e cooperativo, há também a possibilidade de threads diferentes com prioridades diferentes. Por exemplo, provavelmente é mais importante executar em tempo hábil o encadeamento que está recebendo dados através de um link de comunicação do que aquele que atualiza a exibição da hora do sistema, para que o encadeamento receptor tenha alta prioridade e o encadeamento atualizador de exibição do tempo tenha baixa prioridade . As prioridades do encadeamento desempenham um papel na decisão do agendador de qual encadeamento permitir executar (por exemplo, muito simplificado, os encadeamentos de alta prioridade sempre devem ser executados antes dos encadeamentos de baixa prioridade, portanto, mesmo que o encadeamento de baixa prioridade tenha trabalho a fazer, se o encadeamento de alta prioridade se tornar executável, isso terá precedência), mas essas decisões de agendamento específicas não afetam o design do mecanismo subjacente.


11
Eu amo "a entrada do usuário em particular é extremamente lento"
John Dvorak

Os "threads" que uma CPU "possui" se referem ao número que pode ser executado simultaneamente a qualquer momento. Ele alterna entre os segmentos ativos, dando uma volta a cada, ou compartilhando a CPU por uma fatia de tempo, quando possível. Processos / encadeamentos "bloqueados" ou aguardando E / S (como disco, entrada de teclado / mouse etc.) ou qualquer outra coisa (como primitivas de sincronização como mutexes, etc.) ignoram sua vez.
LawrenceC

1
É bom pedir comentários, mas eles não são adequados para discussões prolongadas e, em algum momento, tornam-se difíceis de ler. Você pode levar isso para o bate-papo de superusuário ? Obrigado.
slhck

1
@slhck Criei uma sala, mas não consegui encontrar nenhuma maneira de migrar a discussão nesses comentários, o que seria legal. É algo que você pode fazer manualmente como moderador? chat.stackexchange.com/rooms/9547/…
um CV

1
Infelizmente não. Há um processo de migração automática que não pode ser acionado manualmente, mas não podemos mover comentários para uma sala de bate-papo. Vamos deixar os comentários aqui por enquanto, mas incentivamos outras pessoas a acompanhar a discussão na sala de bate-papo que você criou.
Slhck 06/07

18

Pense em uma estrada de quatro pistas com 1037 veículos.

Seu sistema operacional precisa de muitos processos em execução para funcionar com muitos serviços. Mesmo os programas gráficos mais simples exigirão programação multithread. Quando você pensa em muitos programas abertos, vê que é necessário compartilhar os recursos de energia da computação.

O que seu gerenciador de tarefas está mostrando é a carga atual do sistema. O que suas especificações de compilação estão mostrando é quantos threads (no front-end) estão sendo aceitos para execução paralela. Sem entrar muito na diferença entre os recursos hyperthreading e multicore, com a aceitação de mais threads de front-end lógicos, um sistema geralmente terá um desempenho melhor.


8
"Mesmo os programas gráficos mais simples exigirão programação multithread." Errado. É perfeitamente possível escrever aplicativos GUI de thread único; até o Windows 95, para todos os efeitos, todos fizeram dessa maneira. Isso torna algumas tarefas mais complicadas (por exemplo, a impressão em segundo plano é trivial com vários encadeamentos, mas decididamente não trivial em um único aplicativo encadeado, principalmente se você também tiver memória restrita, como era o caso), mas há uma enorme diferença entre " X é facilitado por Y "e" X requer Y ".
um CVn

8
@ MichaelKjörling: "até o Windows 95, para todos os efeitos, todos fizeram dessa maneira" * - sério? Mesmo em sistemas * nix executando o Motif nos anos 80?
Larsh

@LarsH Bom ponto, e um que pensei tarde demais para editar no comentário. Mas isso não nega o ponto: a saber, que é perfeitamente possível escrever aplicativos GUI de thread único. Você não precisa de multithreading para isso, embora isso facilite (consideravelmente) algumas tarefas (consideravelmente) para o programador.
um CVn

@ MichaelKjörling: Eu concordo, isso não nega seu ponto, que é válido. (Eu não acho que uprego da declaração incorreta nega seu ponto também.)
Larsh

Como um exemplo do que MichaelKjörling disse, o Visual Basic (antes do .NET) como linguagem de programação não tinha suporte para multi-threading. Tudo foi executado em um único segmento. Se você quisesse processar a entrada do usuário no meio de uma operação de execução demorada, telefonaria para DoEventsprocessar a fila de mensagens - mas isso foi feito no mesmo encadeamento e bloquearia essa operação de execução demorada até que todas as mensagens fossem processadas . (Claro, você poderia chamar funções da API Win32 e / ou criar processos adicionais, mas nesse ponto você pode também usar um dos idiomas de nível inferior.)
Bob

5

Devemos dar um passo atrás e nos perguntar: como um computador com uma única CPU pode ter dois threads?

Threads são entidades de software, não hardware. Para ter outro encadeamento, você só precisa de memória para os objetos que compõem o encadeamento, como uma estrutura de descritor e uma pilha.

O sistema operacional alterna entre threads em vários momentos, como em certas interrupções (como uma interrupção do timer) ou quando os threads fazem chamadas para o sistema operacional.

De todos os encadeamentos existentes no sistema, apenas um subconjunto geralmente está em um estado que é comumente chamado de "executável". Os threads executáveis ​​estão ansiosos para executar: eles estão executando ou estão em uma "fila de execução", esperando para serem despachados pelo planejador. Threads que não podem ser executados são "bloqueados", aguardando para adquirir algum recurso ou receber entrada, ou "inativos", como é bloqueado na entrada, onde a "entrada" é a passagem do tempo. Uma "alternância de contexto" ocorre quando a função do planejador no sistema operacional examina a fila de execução de um processador e escolhe um encadeamento diferente para executar.

Não se confunda com "hyperthreading" , que é o nome da Intel para um recurso de hardware específico.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.