Большинство проблем не требуют много процессорного времени. Действительно, одноядерные процессоры достаточно быстры для многих целей. Когда вы обнаружите, что ваша программа работает слишком медленно, сначала профилируйте ее и посмотрите на выбранные вами алгоритмы, архитектуру и кеширование. Если этого вам недостаточно, попробуйте разделить проблему на отдельные процессы. Часто это стоит делать просто для изоляции отказов, чтобы вы могли понять, сколько процессора и памяти используется каждым процессом. Кроме того, обычно каждый процесс будет работать на определенном ядре и эффективно использовать кэши процессоров, поэтому вам не придется испытывать значительные накладные расходы на производительность для поддержания согласованности строк кэша. Если вы занимаетесь многопроцессным проектированием и по-прежнему обнаруживаете, что проблема требует больше процессорного времени, чем у вашей машины, у вас есть все возможности для ее расширения в кластере.
Существуют ситуации, когда вам нужно несколько потоков в одном и том же адресном пространстве, но имейте в виду, что потоки действительно трудно понять правильно. Условия гонки, особенно на небезопасных языках, иногда занимают недели для отладки; часто простое добавление трассировки или запуск под отладчиком изменяет время достаточно, чтобы скрыть проблему. Простая установка блокировок повсеместно часто означает, что вы получаете много накладных расходов на блокировку, а иногда и столько разногласий по блокировке, что вы не получаете того преимущества параллелизма, на которое надеялись. Даже если у вас есть правильная блокировка, вам нужно профилировать для настройки когерентности кэша. В конечном счете, если вы хотите действительно настроить некоторый высококонкурентный код, вы, вероятно, в конечном итоге будете рассматривать конструкции без блокировок и более сложные схемы блокировки, чем в современных многопоточных библиотеках.