Em primeiro lugar, os threads não podem acelerar a execução do código. Eles não fazem o computador rodar 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 segmento. Prova: Um sistema de processador único pode executar apenas instruções linearmente. Ter várias linhas de execução é feito pelas interrupções de processamento do sistema operacional, salvando o estado do thread 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 a memória e o armazenamento de dados em disco rígido. Assim, uma instrução "add", por exemplo, executa muito mais rapidamente que uma "busca". Caches e busca de instrução de programa dedicada (não tenho certeza do termo exato aqui) podem combater isso até certo ponto, mas a questão da velocidade permanece.
Threading é uma forma de combater essa incompatibilidade usando a CPU para instruções de limite de CPU enquanto as instruções de IO estão sendo concluídas. Um plano de execução de encadeamento típico provavelmente seria: Busque dados, processe dados, grave dados. Suponha que buscar e escrever demore 3 ciclos e o processamento leve um, para fins ilustrativos. Você pode ver que enquanto o computador está lendo ou escrevendo, ele está fazendo nada por 2 ciclos cada um? 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 busca
- sem operação
- # 2 buscar
- # 1 pronto, processe-o
- escreva # 1
- # 1 busca
- # 2 pronto, processe
- escreva # 2
- buscar # 2
E assim por diante. Obviamente, este é um exemplo um pouco inventado, mas você pode ver como essa técnica pode utilizar o tempo que seria gasto esperando por IO.
Observe que a segmentação conforme mostrado acima só pode aumentar a eficiência em processos altamente vinculados de 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 surra .
Tudo isso é bom para um processador de núcleo único, mas a maioria dos processadores modernos tem dois ou mais núcleos. Os threads ainda servem ao mesmo propósito - para 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 de quantos núcleos estão disponíveis, porque o computador é realmente multitarefa, não comutação de contexto.
Com vários núcleos, os encadeamentos fornecem um método de dividir o trabalho entre os dois núcleos. O acima ainda se aplica para cada núcleo individual; Um programa que executa uma eficiência máxima com dois encadeamentos em um núcleo provavelmente executará com eficiência máxima com cerca de quatro encadeamentos em dois núcleos. (A eficiência é medida aqui por execuções mínimas de instrução 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 terá certeza de que ela bloqueia os locais de memória apropriados antes de ler / gravar nela. (Eu li que ele usa um sinalizador especial na memória para isso, mas isso pode ser feito de várias maneiras). Como um programador com linguagens de alto nível, você não precisa se preocupar com nada mais em dois núcleos como você teria que com um.
TL; DR: Os segmentos podem dividir o trabalho para permitir que o computador processe várias tarefas de forma assíncrona. Isso permite que o computador seja executado com eficiência máxima, utilizando todo o tempo de processamento disponível, em vez de bloquear quando um processo está aguardando um recurso.