OriginalGriff
Вы должны знать, что нарезание резьбы - это не "волшебная пуля", которая одним махом решит все ваши проблемы с производительностью-ее нужно тщательно продумать и спланировать, или она может сделать две вещи:
1) замедлите свой компьютер до обхода и сделайте ваше приложение значительно медленнее, чем оно начиналось.
2) сбой или полная блокировка вашего приложения.
Причины этого просты:
1) потоки требуют двух вещей для запуска: памяти и свободного ядра. Память будет иметь по меньшей мере размер системного стека на вашем языке (обычно около 1 МБ для Windows, 8 МБ для Linux) плюс некоторые накладные расходы для самого потока и еще больше для любых объектов на основе памяти, которые создает каждый поток; и поток может работать только тогда, когда ядро становится доступным. Если вы создадите больше потоков, чем у вас есть ядер, то большинство из них будут тратить много времени, сидя в ожидании ядра, чтобы быть доступными.
Чем больше потоков вы генерируете, тем хуже становятся проблемы: чем больше потоков, тем больше нагрузка на систему, чтобы переключать потоки чаще, и это также занимает основное время. Все потоки в системе образуют все процессы, имеющие общие ядра в машине, поэтому другим приложениям и системным потокам также требуется их время для запуска. Добавьте слишком много, и система будет тратить все больше и больше своего времени, пытаясь решить, какой поток запустить, и производительность снизится. Генерируйте достаточное количество потоков, чтобы превысить физическую память в вашем компьютере, и производительность внезапно получает огромный удар, когда система виртуальной памяти входит и начинает нарезать страницы памяти на жесткий диск.
2) несколько потоков внутри процесса должны быть потокобезопасными, потому что они совместно используют память и другие ресурсы - а это означает, что может произойти несколько вещей:
2а) если двум потокам нужен один и тот же ресурс, то вы легко можете оказаться в ситуации, когда поток а заблокировал ресурс X и хочет Y, а поток в заблокировал ресурс Y и хочет X. В этот момент произошло "смертельное объятие", и никакая другая нить (ни одна другая, которая нуждается в X или Y, не может работать снова.
2b) если ваш код не является потокобезопасным, то разные потоки могут пытаться читать и / или изменять одну и ту же память одновременно: это часто происходит при попытке добавить или удалить элементы из коллекции. В этот момент начинают происходить странные вещи, вплоть до сбоя вашего приложения.
2c) если ресурсы имеют конечную емкость - например, пропускную способность в интернет - соединении, - то плохая потоковая передача может легко использовать все это - на любом конце канала. Если у вас закончится емкость, ваши потоки остановятся в ожидании этого (и все остальные, использующие соединение, также пострадают). Если на другом конце провода не хватает мощности, он может заикаться, замедляться, аварийно завершать работу или предполагать, что вы подвергаетесь DDOS-атаке, и принимать меры предосторожности.
Вы не можете просто пойти "многопоточно это" и предположить, что это сработает: это то, что требует очень, очень тщательного планирования.
Подумайте об этом так: если у Вас очень большой автобус, это медленный способ добраться от А до В, но когда вы усредняете его по большому количеству пассажиров, это довольно быстро. Но если вы посадите каждого пассажира в отдельный автомобиль, теоретически они все могут добраться туда быстрее - за исключением того, что вы ставите гораздо больше транспортных средств на одних и тех же дорогах, что означает больше шансов на пробки, аварии, поломки и т. д. Поставьте слишком много на одни и те же дороги, и они будут заблокированы автомобилями, и никто не сможет никуда двигаться, потому что на их пути стоит машина ...