Есть несколько очень полезных преимуществ для многопоточности; у нас может быть несколько процессов, запущенных одновременно, и несколько потоков, работающих в этих процессах. Итак, со всеми этими преимуществами, почему бы нам просто не использовать новые потоки для всех наших методов? Разве это не заставило бы все бежать быстро? На самом деле, нет. На самом деле, мы увидим в этом разделе, что может произойти совершенно противоположное, если мы чрезмерно используем многопоточность.
Многопоточные приложения требуют ресурсов. Потоки требуют памяти для хранения контейнера локального потока. Как вы можете себе представить, количество используемых потоков ограничено объемом доступной памяти. Память довольно недорогая в наши дни, поэтому многие компьютеры имеют большой объем памяти. Тем не менее, вы не должны предполагать, что это так. Если вы запускаете приложение на неизвестной конфигурации оборудования, вы не можете предполагать, что вашему приложению будет достаточно памяти. Кроме того, вы не можете предполагать, что ваш процесс будет единственным порождающим потоком и потребляющим системные ресурсы. То, что у машины много памяти, еще не значит, что это все для вашего приложения.
Вы также обнаружите, что каждый поток также несет дополнительную нагрузку на процессор. Создание слишком большого количества потоков в ваших приложениях ограничит время выполнения вашего потока. Следовательно, ваш процессор может потратить больше времени на переключение между потоками, а не выполнять инструкции, содержащиеся в потоках. Если ваше приложение создает больше потоков, ваше приложение получит больше времени выполнения, чем все другие процессы с меньшим количеством потоков.
Чтобы облегчить понимание этой концепции, возьмите параллельный пример, который вы найдете в вашем местном продуктовом магазине. Два кассира сканируют продукты для своих клиентов. Однако есть только один упаковщик, который по очереди переключается между двумя кассирами. Упаковщик довольно эффективен для того, чтобы прыгать туда-сюда между двумя регистрами и упаковывать продукты, потому что они не накапливаются быстрее, чем упаковщик может запаковать продукты. Однако, если еще два кассира откроют дорожки, станет очевидно, что упаковщик потратит больше времени, прыгая туда-сюда между регистрами, чем тратит деньги на упаковку продуктов. В конце концов, в магазине потребуется еще один упаковщик. В случае с многопоточностью считайте кассиры приложениями или потоками, а упаковщик — процессором. Процессор должен переключаться между потоками.
Фраза «слишком много тем» является довольно общим термином — и это правильно. То, что составляет «слишком много» в одной системе, может быть хорошо в другой. Поскольку конфигурации оборудования в значительной степени определяют количество потоков, доступных в системе, «слишком много» — это не поддающаяся количественному определению переменная без конкретных деталей конфигурации и большого количества тестирования.
Именно по этим причинам Microsoft рекомендует использовать как можно меньше потоков в своих приложениях. Это ограничивает количество ресурсов, требуемых операционной системой.