O padrão: dividir, processar, combinar
Os três exemplos anteriores seguem o mesmo padrão, apesar de resolverem problemas diferentes:
- Dividir o trabalho em partes independentes.
- Processar cada parte numa thread separada.
- Combinar os resultados após todas as threads terminarem (via
join).
No download concorrente, a fase de combinação nem existe (cada thread é autossuficiente). Na soma e no máximo, a combinação é trivial: uma adição ou uma comparação.
Esses exemplos funcionam sem nenhum mecanismo de sincronização porque as
threads não precisam se comunicar entre si durante a execução. Cada uma opera
sobre sua própria fatia de dados, e a única troca de informação acontece no
join, quando a thread principal coleta os resultados.
Mas nem todo problema se decompõe dessa forma.