O que vários threads podem fazer que um único thread não pode? [fechadas]

100

Embora os threads possam acelerar a execução do código, eles são realmente necessários? Cada pedaço de código pode ser feito usando um único thread ou existe algo que só pode ser realizado usando vários threads?

Pássaro nervoso
fonte
29
Com base em algumas das respostas já postadas aqui, acho que alguns esclarecimentos estão em ordem. O objetivo do encadeamento é permitir que os computadores (pareçam) façam mais de uma coisa por vez. Se isso for feito usando um computador com um único núcleo, você não verá nenhuma aceleração geral. O que você verá é desbloquear; em um programa de thread único, a interface do usuário será bloqueada enquanto os cálculos estiverem sendo realizados. Em um programa multithread, a interface do usuário ainda pode ser utilizada enquanto os cálculos ocorrem em segundo plano.
Robert Harvey
11
Obviamente, se você possui vários núcleos de processador em seu computador (o que é comum hoje em dia), seu programa pode usar threads para tirar proveito de núcleos adicionais para executar seu processamento, e você verá uma aceleração, porque está gastando mais potência em seu problema de computação. Se você não usar threads, seu programa utilizará apenas um núcleo de processador, o que é bom se for tudo o que você precisa.
Robert Harvey
14
Um programa de thread único não pode bloquear recursos da mesma maneira que um programa multiencadeado.
precisa saber é o seguinte
3
Resposta: executado em dois núcleos
Daniel Pequenas
6
Resposta: causar um impasse.
Job

Respostas:

111

Primeiro de tudo, os threads não podem acelerar a execução do código. Eles não fazem o computador funcionar mais rápido. Tudo o que eles podem fazer é aumentar a eficiência do computador usando o tempo que seria desperdiçado. Em certos tipos de processamento, essa otimização pode aumentar a eficiência e diminuir o tempo de execução.

A resposta simples é sim. Você pode escrever qualquer código para ser executado em um único encadeamento. Prova: Um sistema de processador único pode executar instruções apenas linearmente. Ter várias linhas de execução é feita pelas interrupções do processamento do sistema operacional, salvando o estado do encadeamento atual e iniciando outro.

A resposta complexa é ... mais complexa! A razão pela qual os programas multithread podem ser mais eficientes que os lineares é devido a um "problema" de hardware. A CPU pode executar cálculos mais rapidamente do que IO de memória e armazenamento físico. Portanto, uma instrução "add", por exemplo, executa muito mais rapidamente do que uma "busca". Caches e busca de instruções de programas dedicados (não tenho certeza do termo exato aqui) podem combater isso até certo ponto, mas o problema da velocidade permanece.

O encadeamento é uma maneira de combater essa incompatibilidade usando a CPU para obter instruções vinculadas à CPU enquanto as instruções de E / S estão sendo concluídas. Um plano de execução de encadeamento típico provavelmente seria: Buscar dados, processar dados, gravar dados. Suponha que a busca e a gravação levem três ciclos e o processamento leve um, para fins ilustrativos. Você pode ver que, enquanto o computador está lendo ou escrevendo, ele não está fazendo nada por 2 ciclos cada? Claramente, está sendo preguiçoso e precisamos quebrar nosso chicote de otimização!

Podemos reescrever o processo usando o threading para usar esse tempo perdido:

  1. # 1 buscar
  2. nenhuma operação
  3. # 2 buscar
  4. # 1 está pronto, processe-o
  5. escreva # 1
  6. # 1 buscar
  7. # 2 está pronto, processe-o
  8. escreva # 2
  9. buscar # 2

E assim por diante. Obviamente, este é um exemplo um tanto artificial, mas você pode ver como essa técnica pode utilizar o tempo que seria gasto esperando pela E / S.

Observe que o encadeamento, como mostrado acima, só pode aumentar a eficiência em processos fortemente vinculados a E / S. Se um programa estiver calculando principalmente as coisas, não haverá muitos "buracos" nos quais poderíamos trabalhar mais. Além disso, há uma sobrecarga de várias instruções ao alternar entre threads. Se você executar muitos threads, a CPU passará a maior parte do tempo trocando e não trabalhando muito no problema. Isso é chamado de thrashing .

Tudo está bem para um processador de núcleo único, mas a maioria dos processadores modernos tem dois ou mais núcleos. Os threads ainda têm o mesmo objetivo - maximizar o uso da CPU, mas desta vez temos a capacidade de executar duas instruções separadas ao mesmo tempo. Isso pode diminuir o tempo de execução por um fator, no entanto, muitos núcleos estão disponíveis, porque o computador é realmente multitarefa, não alternando o contexto.

Com vários núcleos, os threads fornecem um método de dividir o trabalho entre os dois núcleos. O acima ainda se aplica a cada núcleo individual; Um programa que execute uma eficiência máxima com dois threads em um núcleo provavelmente executará com eficiência máxima com cerca de quatro threads em dois núcleos. (A eficiência é medida aqui por execuções mínimas de instruções NOP.)

Os problemas com a execução de threads em vários núcleos (em oposição a um único núcleo) geralmente são resolvidos pelo hardware. A CPU garantirá que bloqueie os locais de memória apropriados antes de ler / gravar nela. (Eu li que ele usa um bit de sinalizador especial na memória para isso, mas isso pode ser realizado de várias maneiras.) Como programador com linguagens de nível superior, você não precisa se preocupar com mais nada em dois núcleos. teria que ser com um.

TL; DR: os threads podem dividir o trabalho para permitir que o computador processe várias tarefas de forma assíncrona. Isso permite que o computador funcione com a máxima eficiência utilizando todo o tempo de processamento disponível, em vez de travar quando um processo está aguardando por um recurso.

Michael K
fonte
17
Excelente resposta. Eu só queria elaborar que, após um certo ponto, adicionar mais threads pode realmente tornar o programa mais lento , porque todo o tempo "desperdiçado" anteriormente é utilizado, e agora você está adicionando apenas troca de contexto adicional e sobrecarga de sincronização.
Karl Bielefeldt
8
+1 para descrever como os threads ajudam no processamento de bloqueio de E / S. Outro uso de threads é permitir que a interface do usuário continue a processar ações do usuário (movimento do mouse, barras de progresso, pressionamentos de teclas), para que a percepção do usuário seja de que o programa não "congelou".
#
3
Mais uma adição: a rigor , os threads não acrescentam expressividade à maioria dos idiomas; você poderia, se fosse absolutamente necessário, implementar toda a multiplexação e obter os mesmos resultados. Na prática, porém, isso equivaleria a reimplementar toda a sua biblioteca de threads - assim como a recursão não é estritamente necessária, mas pode ser emulada escrevendo sua própria pilha de chamadas.
Kilian Foth 01/08/19
9
@ James: Eu classificaria o processamento da interface do usuário como apenas outra forma de E / S. Talvez o pior, pois os usuários tendem a ser atrasados ​​e não lineares. :)
TMN
7
Há uma suposição silenciosa na pergunta e resposta em torno do computador como núcleo único ou CPU. Meu relógio tem dois núcleos, duvido que a suposição seja válida em qualquer máquina moderna.
Blueberryfields
37

O que vários threads podem fazer que um único thread não pode?

Nada.

Esboço simples de prova:

  • [Conjectura de Church-Turing] ⇒ Tudo o que pode ser calculado pode ser calculado por uma Máquina Universal de Turing.
  • Uma máquina universal de Turing é de rosca única.
  • Portanto, tudo o que pode ser calculado pode ser calculado por um único thread.

Observe, no entanto, que há uma grande suposição oculta: a linguagem usada no thread único é Turing-complete.

Portanto, a pergunta mais interessante seria: "A adição de apenas multi-threading a um idioma não completo de Turing pode torná-lo completo?" E eu acredito que a resposta é "Sim".

Vamos usar os idiomas funcionais totais. [Para aqueles que não estão familiarizados: assim como a Programação Funcional está programando com funções, a Programação Funcional Total está programando com o total de funções.]

As linguagens funcionais totais obviamente não são completas para Turing: você não pode escrever um loop infinito em uma TFPL (na verdade, essa é praticamente a definição de "total"), mas você pode em uma máquina de Turing; portanto, existe pelo menos um programa que não pode ser gravado em um TFPL, mas em um UTM; portanto, os TFPLs são menos poderosos em termos computacionais que os UTMs.

No entanto, assim que você adiciona o encadeamento a um TFPL, obtém loops infinitos: basta fazer cada iteração do loop em um novo encadeamento. Cada thread individual sempre retorna um resultado, portanto é Total, mas cada thread também gera um novo thread que executa a próxima iteração, ad infinitum.

Eu acho que essa linguagem seria completa em Turing.

No mínimo, responde à pergunta original:

O que vários threads podem fazer que um único thread não pode?

Se você tem uma linguagem que não pode fazer loops infinitos, em seguida, multi-threading permite que você faça loops infinitos.

Observe, é claro, que gerar um encadeamento é um efeito colateral e, portanto, nossa linguagem estendida não é mais não apenas total, como também não é mais funcional.

Jörg W Mittag
fonte
13
Desde que você apresentou uma "prova", não posso me impedir de "bem, na verdade ..." ing você. Eu acho que você está abusando da noção de computabilidade. A prova é uma coisa fofa e eu entendo o seu ponto, mas não está realmente no nível certo de abstração. Não ser capaz de fazer as coisas não é o mesmo como não sendo capaz de calcular , por exemplo, você não pode usar a sua prova para dizer, porque máquina de Turing pode computar "todas as funções computáveis", ele pode fazê- lo em 3 segundos. Estritamente falando, uma única máquina encadeada sem interrupções não pode acessar a E / S enquanto mantém seu processador ocupado fazendo cálculos.
precisa saber é o seguinte
1
E, nenhum computador real é uma máquina de Turing.
Jens
1
@ColeJohnson: Um impasse é um detalhe de implementação. A saída visível é "sem interrupção", o que é facilmente possível com um único thread.
Heinzi 12/09
1
@ Heinzi: "facilmente factível" é um eufemismo. Se bem me lembro, o segundo ou terceiro programa que eu escrevi fez exatamente isso! ;-)
Joachim Sauer
1
Se o universo é único fio ed, então o que é corda teoria? Você não pode discutir com ciência como esta.
corsiKa
22

Em teoria, tudo o que um programa multithread faz pode ser feito com um programa de thread único, apenas mais devagar.

Na prática, a diferença de velocidade pode ser tão grande que não há como usar um programa de thread único para a tarefa. Por exemplo, se você tem um trabalho de processamento de dados em lote executando todas as noites e leva mais de 24 horas para concluir um único encadeamento, você não tem outra opção senão torná-lo multithread. (Na prática, o limite provavelmente é ainda menor: geralmente essas tarefas de atualização devem terminar até de manhã cedo, antes que os usuários comecem a usar o sistema novamente. Além disso, outras tarefas podem depender delas, que também devem ser concluídas durante a mesma noite. o tempo de execução disponível pode ser tão baixo quanto algumas horas / minutos.)

Fazer o trabalho de computação em vários threads é uma forma de processamento distribuído; você está distribuindo o trabalho por vários segmentos. Outro exemplo de processamento distribuído (usando vários computadores em vez de vários threads) é o protetor de tela SETI: processar muitos dados de medição em um único processador levaria muito tempo e os pesquisadores prefeririam ver os resultados antes da aposentadoria ;-) No entanto, eles não tem orçamento para alugar um supercomputador por tanto tempo; assim, eles distribuem o trabalho por milhões de PCs domésticos, para torná-lo mais barato.

Péter Török
fonte
O protetor de tela SETI é um exemplo de encadeamento no sentido em que é executado em um encadeamento em segundo plano no seu computador; você ainda pode fazer outras coisas no seu computador enquanto ele processa dados em segundo plano. Sem o segmento, haveria uma pausa enquanto o protetor de tela SETI executasse seus cálculos; você teria que esperar o término para poder continuar seu próprio trabalho.
Robert Harvey
3
@ Robert: Eu acho que Péter está usando o SETI @ Home para explicar o conceito de dividir o trabalho para rodar em vários processadores. A computação distribuída é obviamente diferente da multithreading, mas o conceito é semelhante.
Steven
5
Eu acho que o exemplo do SETI é computação distribuída em vez de multithreaded. Conceitos semelhantes, mas não a mesma coisa.
11

Embora os encadeamentos pareçam ser um pequeno passo em relação à computação sequencial, na verdade, eles representam um grande passo. Eles descartam as propriedades mais essenciais e atraentes da computação seqüencial: compreensibilidade, previsibilidade e determinismo. Os threads, como modelo de computação, são extremamente não-determinísticos, e o trabalho do programador passa a podar esse não-determinismo.

- O problema com os threads (www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf).

Embora haja algumas vantagens de desempenho que podem ser obtidas com o uso de encadeamentos em que você pode distribuir o trabalho em vários núcleos, eles geralmente têm um ótimo preço.

Uma das desvantagens do uso de encadeamentos ainda não mencionados aqui é a perda de compartimentação de recursos obtida com espaços de processo encadeados únicos. Por exemplo, digamos que você encontre o caso de um segfault. Em alguns casos, é possível recuperar isso em um aplicativo com vários processos, pois você simplesmente deixa a criança com falha morrer e reaparece uma nova. É o caso do backend pré-fork do Apache. Quando uma instância httpd falha, o pior caso é que a solicitação HTTP específica pode ser descartada para esse processo, mas o Apache gera um novo filho e, muitas vezes, a solicitação, se apenas for reenviado e atendido. O resultado final é que o Apache como um todo não é eliminado com o encadeamento defeituoso.

Outra consideração nesse cenário são vazamentos de memória. Existem alguns casos em que você pode lidar com um encadeamento de falhas de encadeamento (no UNIX, a recuperação de alguns sinais específicos - até segfault / fpviolation - é possível), mas mesmo nesse caso, você pode ter vazado toda a memória alocada por esse encadeamento (malloc, novo etc.). Assim, enquanto o processo pode permanecer, ele vaza mais e mais memória ao longo do tempo a cada falha / recuperação. Novamente, existem maneiras de minimizar isso, como o uso de conjuntos de memória do Apache. Mas isso ainda não protege contra a memória que pode ter sido alocada por bibliotecas de terceiros que o encadeamento pode estar usando.

E, como algumas pessoas apontaram, entender as primitivas de sincronização é talvez a coisa mais difícil de se acertar. Esse problema por si só - apenas acertar a lógica geral para todo o seu código - pode ser uma enorme dor de cabeça. Os deadlocks misteriosos tendem a acontecer nos momentos mais estranhos e, às vezes, até o programa estar em produção, o que torna a depuração ainda mais difícil. Adicione a isso o fato de que as primitivas de sincronização geralmente variam amplamente com a plataforma (Windows vs. POSIX), e a depuração pode ser mais difícil, além da possibilidade de condições de corrida a qualquer momento (inicialização / inicialização, tempo de execução e desligamento), programar com threads realmente tem pouca piedade para iniciantes. E mesmo para especialistas, ainda há pouca misericórdia apenas porque o conhecimento do encadeamento em si não minimiza a complexidade em geral. Às vezes, cada linha de código encadeado parece exponencialmente aumentar a complexidade geral do programa, além de aumentar a probabilidade de surgir um impasse oculto ou uma condição estranha de corrida a qualquer momento. Também pode ser muito difícil escrever casos de teste para descobrir essas coisas.

É por isso que alguns projetos como o Apache e o PostgreSQL são, em grande parte, baseados em processos. O PostgreSQL executa todos os threads de back-end em um processo separado. É claro que isso ainda não alivia o problema das condições de sincronização e corrida, mas adiciona bastante proteção e, de certa forma, simplifica as coisas.

Vários processos, cada um executando um único encadeamento de execução, podem ser muito melhores do que vários encadeamentos executados em um único processo. E com o advento de grande parte do novo código ponto a ponto como AMQP (RabbitMQ, Qpid etc.) e ZeroMQ, é muito mais fácil dividir threads em diferentes espaços de processo e até máquinas e redes, simplificando bastante as coisas. Mas ainda assim, não é uma bala de prata. Ainda há complexidade para lidar. Você acabou de mover algumas de suas variáveis ​​do espaço do processo para a rede.

A conclusão é que a decisão de entrar no domínio dos threads não é clara. Depois de entrar nesse território, quase instantaneamente tudo se torna mais complexo e novas raças de problemas entram em sua vida. Pode ser divertido e legal, mas é como energia nuclear - quando as coisas dão errado, elas podem ir mal e rápido. Lembro-me de fazer uma aula de treinamento de crítica há muitos anos e eles mostraram fotos de alguns cientistas de Los Alamos que brincavam com plutônio nos laboratórios da Segunda Guerra Mundial. Muitos tomaram poucas ou nenhuma precaução contra o evento de uma exposição e, num piscar de olhos - em um único flash brilhante e indolor, tudo acabaria para eles. Dias depois eles estavam mortos. Richard Feynman mais tarde se referiu a isso como " fazendo cócegas na cauda do dragão. "É o tipo de brincadeira com tópicos (pelo menos para mim, pelo menos). Parece bastante inócuo no começo, e quando você é mordido, você está coçando a cabeça com a rapidez com que as coisas azedaram. Mas pelo menos os tópicos venceram te matar.

Mike Owens
fonte
Minha resposta TL; DR empalidece em comparação com essa boa parte sobre o que threads únicos não farão por você.
bmike
1
coffee break da tarde
Mike Owens
10

Primeiro, um único aplicativo encadeado nunca tirará vantagem de uma CPU multi-core ou hyper-threading. Mas, mesmo em um único núcleo, a CPU de rosca única, com multiencadeamento, tem vantagens.

Considere a alternativa e se isso a faz feliz. Suponha que você tenha várias tarefas que precisam ser executadas simultaneamente. Por exemplo, você deve continuar se comunicando com dois sistemas diferentes. Como você faz isso sem multi-threading? Você provavelmente criaria seu próprio agendador e deixaria chamar as diferentes tarefas que precisam ser executadas. Isso significa que você precisa dividir suas tarefas em partes. Você provavelmente precisa atender a algumas restrições em tempo real, para garantir que suas peças não ocupem muito tempo. Caso contrário, o cronômetro expirará em outras tarefas. Isso dificulta a divisão de uma tarefa. Quanto mais tarefas você precisar gerenciar, mais dividido será necessário e mais complexo o seu agendador se tornará para atender a todas as restrições.

Quando você tem vários threads, a vida pode se tornar mais fácil. Um planejador preventivo pode parar um encadeamento a qualquer momento, manter seu estado e reiniciar outro. Ele será reiniciado quando o seu thread chegar. Vantagens: a complexidade de escrever um agendador já foi feita para você e você não precisa dividir suas tarefas. Além disso, o planejador é capaz de gerenciar processos / encadeamentos que você nem conhece. E também, quando um encadeamento não precisa fazer nada (está aguardando algum evento), ele não ocupará ciclos de CPU. Isso não é tão fácil de realizar quando você está criando seu planejador de thread único inativo. (colocar algo para dormir não é tão difícil, mas como ele acorda?)

A desvantagem do desenvolvimento multithread é que você precisa entender sobre problemas de simultaneidade, estratégias de bloqueio e assim por diante. Desenvolver código multiencadeado sem erros pode ser bastante difícil. E a depuração pode ser ainda mais difícil.

Marca
fonte
9

existe algo que só pode ser realizado usando vários threads?

Sim. Você não pode executar código em várias CPUs ou núcleos de CPU com um único encadeamento.

Sem várias CPUs / núcleos, os threads ainda podem simplificar o código que é executado conceitualmente em paralelo, como o tratamento do cliente em um servidor - mas você pode fazer o mesmo sem os threads.

Lama
fonte
6

Os threads não são apenas sobre velocidade, mas sobre simultaneidade.

Se você não possui um aplicativo em lote como o @Peter sugeriu, mas um kit de ferramentas da GUI como o WPF, como você pode interagir com os usuários e a lógica de negócios com apenas um thread?

Além disso, suponha que você esteja construindo um servidor Web. Como você atenderia mais de um usuário simultaneamente com apenas um thread (supondo que nenhum outro processo)?

Existem muitos cenários em que apenas um thread simples não é suficiente. É por isso que avanços recentes, como o processador Intel MIC, com mais de 50 núcleos e centenas de threads, estão ocorrendo.

Sim, programação paralela e simultânea é difícil. Mas necessário.

Randolf Rincón Fadul
fonte
3
"Apenas um thread" pode significar várias coisas - você pode usar continuações delimitadas para simular multitarefa cooperativa em um único thread (SO ou verde), por exemplo.
Frank Shearar
Claro, mas estou dando um pouco de contexto à pergunta @Frank +1 da dica.
Randolf Rincón Fadul
3
Os encadeamentos podem facilitar, mas todas as tarefas que você mencionou podem ser realizadas sem encadeamentos, e costumavam ser. Por exemplo, o loop canônico da GUI costumava ser while (true) {process GUI events; calcular um pouco}. Não são necessários tópicos.
KeithB
Existem servidores da web de processo único e de processo único. lighttpd, por exemplo, ou thttpd ou nginx (embora o último possa executar mais de um processo, mas o padrão seja um. Também é sempre um thread único). Eles não têm absolutamente nenhum problema em atender mais de um usuário.
StasM
6

O Multi-Threading pode deixar a interface da GUI ainda ser responsiva durante longas operações de processamento. Sem multiencadeamento, o usuário ficaria preso assistindo a um formulário bloqueado enquanto um longo processo está sendo executado.

LarsTech
fonte
Isso não está totalmente correto. Em teoria, você pode dividir sua operação longa em muitas menores e atualizar o processamento de eventos no meio.
Sebastian Negraszus
@Sebastion N. Mas se o longo processo não puder ser refatorado para outros menores? A capacidade de executar o processo em outro encadeamento pode liberar o encadeamento da GUI (o encadeamento principal) para continuar respondendo.
LarsTech 13/08
5

O código multithread pode bloquear a lógica do programa e acessar dados obsoletos de maneiras que um único thread não pode.

Os threads podem pegar um bug obscuro de algo que um programador comum pode depurar e movê-lo para o reino, onde são contadas histórias sobre a sorte necessária para pegar o mesmo bug com suas calças quando um programador de alerta estava olhando apenas o momento certo.

bmike
fonte
4

os aplicativos que lidam com o bloqueio de E / S que também precisam permanecer responsivos a outras entradas (a GUI ou outras conexões) não podem ser executados individualmente

a adição de métodos de verificação na lib de E / S para ver o quanto pode ser lido sem bloqueio pode ajudar isso, mas poucas bibliotecas oferecem garantias completas sobre isso

catraca arrepiante
fonte
Eles podem ser de rosca única (e geralmente eram). O código diz ao kernel para iniciar algumas E / S e recebe um sinal quando é concluído. Enquanto aguarda o sinal, ele pode fazer outro processamento.
KeithB
@keith que é não que bloqueia IO eu disse especificamente bloqueio
catraca aberração
Mas por que você faria o bloqueio de E / S se quiser permanecer responsivo? Existe algum IO de bloqueio que geralmente não tem uma alternativa sem bloqueio? Não consigo pensar em nada.
KeithB
RMI @keith de java está bloqueando e enquanto você pode implementar uma chamada de retorno (mas isso cria outro segmento) com ele, mas que pode ser bloqueada por firewalls
catraca aberração
Isso soa como uma limitação do Java RMI, não uma limitação inerente ao código de thread único. Além disso, se você estiver executando o RMI, terá um "thread" de execução separado, apenas em uma máquina remota.
KeithB
4

Muitas respostas boas, mas não tenho certeza de nenhuma frase exatamente como eu faria - Talvez isso ofereça uma maneira diferente de ver:

Threads são apenas uma simplificação de programação como Objects ou Actors ou for loops (Sim, qualquer coisa que você implemente com loops, você pode implementar com if / goto).

Sem threads, você simplesmente implementa um mecanismo de estado. Eu tive que fazer isso muitas vezes (a primeira vez que eu fiz isso, eu nunca tinha ouvido falar sobre isso - apenas fiz uma grande declaração de switch controlada por uma variável "State"). Máquinas de estado ainda são bastante comuns, mas podem ser irritantes. Com os fios, uma grande parte do clichê desaparece.

Eles também tornam mais fácil para um idioma dividir a execução em tempo de execução em blocos compatíveis com várias CPUs (o mesmo acontece com os atores, acredito).

Java fornece threads "verdes" em sistemas nos quais o sistema operacional não oferece QUALQUER suporte de segmentação. Nesse caso, é mais fácil ver que eles claramente nada mais são do que uma abstração de programação.

Bill K
fonte
+1 - Threads fornecem apenas uma abstração para paralelismo em máquinas basicamente seqüenciais, assim como linguagens de programação de alto nível fornecem uma abstração de código de máquina.
Mouviciel 6/10/11
0

Os sistemas operacionais usam o conceito de divisão de tempo, em que cada thread recebe a hora de executar e é antecipada. Uma abordagem como essa pode substituir a segmentação como está agora, mas escrever seus próprios planejadores em cada aplicativo seria um exagero. Além disso, você teria que trabalhar com dispositivos de E / S e assim por diante. E exigiria algum suporte do lado do hardware, para que você pudesse acionar interrupções para que seu agendador funcionasse. Basicamente, você escreveria um novo sistema operacional toda vez.

Em geral, o encadeamento pode melhorar o desempenho nos casos em que os encadeamentos aguardam a E / S ou estão em suspensão. Também permite criar interfaces que sejam responsivas e permitir processos de parada enquanto você executa tarefas longas. E também, o encadeamento aprimora as coisas em verdadeiras CPUs multicore.

Codificador
fonte
0

Primeiro, os threads podem fazer duas ou mais coisas ao mesmo tempo (se você tiver mais de um núcleo). Embora você também possa fazer isso com vários processos, algumas tarefas simplesmente não se distribuem muito bem por vários processos.

Além disso, algumas tarefas possuem espaços que você não pode evitar facilmente. Por exemplo, é difícil ler dados de um arquivo em disco e também fazer com que seu processo faça outra coisa ao mesmo tempo. Se sua tarefa exigir necessariamente muitos dados de leitura do disco, seu processo passará muito tempo aguardando o disco, não importa o que você faça.

Segundo, os threads podem permitir que você evite otimizar grandes quantidades de seu código que não são críticas para o desempenho. Se você tiver apenas um único encadeamento, cada pedaço de código é crítico para o desempenho. Se bloquear, você estará afundado - nenhuma tarefa que seria executada por esse processo poderá avançar. Com os encadeamentos, um bloco afetará apenas esse encadeamento e outros encadeamentos poderão surgir e trabalhar em tarefas que precisam ser executadas por esse processo.

Um bom exemplo é o código de tratamento de erros executado com pouca frequência. Digamos que uma tarefa encontre um erro muito pouco frequente e o código para lidar com esse erro precise paginar na memória. Se o disco estiver ocupado e o processo tiver apenas um único encadeamento, nenhum avanço poderá ser feito até que o código para lidar com esse erro possa ser carregado na memória. Isso pode causar uma resposta explosiva.

Outro exemplo é se você raramente precisar fazer uma pesquisa no banco de dados. Se você esperar a resposta do banco de dados, seu código sofrerá um grande atraso. Mas você não quer se dar ao trabalho de tornar todo esse código assíncrono, porque é tão raro que você precisa fazer essas pesquisas. Com um tópico para fazer esse trabalho, você obtém o melhor dos dois mundos. Um encadeamento para fazer este trabalho torna o desempenho não crítico como deveria ser.

David Schwartz
fonte