Это не столько теоретические детали, сколько подробности практической реализации, которые запутывают людей.
Как обстоят дела с неизменяемыми структурами данных?
Все время люди пытаются обновить структуру данных из нескольких потоков, считают это слишком сложным, и кто-то выкрикивает «использовать неизменные структуры данных!», И поэтому наш постоянный кодер пишет это:
ImmutableSet set;
ThreadLoop1()
foreach(Customer c in dataStore1)
set = set.Add(ProcessCustomer(c));
ThreadLoop2()
foreach(Customer c in dataStore2)
set = set.Add(ProcessCustomer(c));
Кодер всю свою жизнь слышал, что неизменяемые структуры данных можно обновлять без блокировки, но новый код не работает по понятным причинам.
Даже если вы нацелены на академиков и опытных разработчиков, небольшое введение в основы неизменяемых идиом программирования не может повредить.
Как разделить примерно одинаковое количество работы между потоками?
Правильный шаг - 1018 * трудно . Иногда вы разбиваете один процесс на 10 000 шагов, которые могут выполняться параллельно, но не все шаги занимают одинаковое количество времени. Если вы разделите работу на 4 потока, и первые 3 потока завершатся за 1 секунду, а последний поток займет 60 секунд, ваша многопоточная программа не намного лучше однопоточной версии, верно?
Итак, как вы распределяете проблемы с примерно одинаковым объемом работы между всеми потоками? Множество хороших эвристических методов решения проблем с упаковкой в мусорное ведро должны быть здесь уместны.
Сколько потоков?
Если ваша проблема хорошо распараллеливается, добавление большего количества потоков должно ускорить ее, верно? Ну, не совсем, здесь нужно учитывать много вещей:
Даже одноядерный процессор, добавление большего количества потоков может сделать программу быстрее, потому что большее количество потоков дает ОС больше возможностей для планирования вашего потока, так что он получает больше времени выполнения, чем однопоточная программа. Но по закону убывающих возвратов добавление большего количества потоков увеличивает переключение контекста, поэтому в определенный момент, даже если у вашей программы больше всего времени выполнения, производительность может быть еще хуже, чем у однопоточной версии.
Так как же вы раскручиваете достаточно потоков, чтобы минимизировать время выполнения?
А если множество других приложений раскручивают потоки и конкурируют за ресурсы, как вы обнаруживаете изменения производительности и автоматически настраиваете программу?