Eu já escrevi sobre isso: https://www.tabnews.com.br/maniero/e-sempre-garantido-que-uma-aplicacao-com-multiplas-threads-rode-mais-rapido-que-usando-uma-unica-thread.
Uma coisa que muita gente acredita é que é necessário de threads para resolver questão de IO e não é, na verdade nem é o correto, apesar de funcionar. Para IO a solução correta é assincronismo, inclusive o sistema operacional tem mecanismos próprios para lidar com isso e está disponível em bibliotecas diversas. Ao mesmo tempo que acham que código assíncrono sempre deixa mais rápido, mas não acontece por si só em código dependente de CPU, ele é bom para IO.
No passado a única solução que existia para IO era threads mesmo, hoje não é assim, mas muita gente aprendeu assim, pega materiais antigos e acha que é necessário ainda.
O uso correto de threads é quando tem muito processamento que pode rodar concorrentemente sem maiores problemas, ou seja, só vale a pena quando oa CPU ficaria ociosa de outra jeito.
Mas para CPU bound geralmente só vale a pena usar a quantidade de threads igual ao número de processadores disponíveis (eventualmente até virtual pode dar algum ganho, mas só em alguns cenários). Porque é desta forma que você pode aproveitar todos os processadores. Se você usar mais threads que o número de processadores começa ficar mais lento porque você paga o custo de troca de contexto de threads que não é barato, por isso algumas linguagens prefeem mecanismo que não dependem de treads diretamente para processamento concorrente, e começa dividir o a capacidade de cada processador, então é só perda.
Já com IO bound isso não acontece porque o proc essador ficaria ocioso nos momentos que está fazendo IO e o uso da thread permite que o processador seja usado e assim ganha tempo, mesmo que não precise usar isso hoje em dia para ter esse ganho, mas é uma forma possível.
O problema do travamento não acontece só em tarefas sequenciais e em algumas sequencias é possível não ter travamento, não é tão simples definir isso, cada algoritmo pode exigir algo diferente.
Então a forma correta de pensar em CPU bound é ter mais threads que processadores, não tem a ver com o fato de ter 1 ou mais processadores, você pode 64 processadores, você não terá 64 vezes mais velocidade tendo 64 threads por causa do custo de administração de threads. Mas fica pior de você tiver mais threads, por exemplo se tiver 128 ficará mais lento que se tiver 64, porque além de não ter ganho porque só tem 64 processadores e eles começam ter sua capacidade dividida, mas também porque a administração fica mais cara por mais trocas de contexto, que inclusive pode afetar o uso de memória, já que pode afetar o cache, e o custo tem potencial de quase inviabilizar o uso em alguns casos. Novamente, não estamos falando de IO bound aqui.
Se o problema for que seu sistema está usando poucas threads e outros sistemas usam muitas, você aumentar a quantidade de threads do seu sistema ajuda o seu sistema, mas piora outras coisas, ou seja, pode não ser uma boa solução. Na verdade esse padrão mostra que algo foi mal planejado, se você precisa de performance no seu sistema ele não deveria concorrer com outros processos, algum dimensionamento está errado, precisa de uma máquina que não atende a demanda, e não é solução uma sistema ferrar os demais. Em uma máquina adequada as outras threads estão dormindo ou em uso muito pequeno.
E quando precisa de mais prioridade o sistema operacional tem maneiras de entregar isso sem ter que criar thrads extras artificialmente para "roubar" processamento dos outros processos, e é mais "educado" fazer desta forma.
Eu gostaria de ver alguma fonte que diga que o kernel dá menos prioridade para quem usa mais.
S2
Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).