Задать вопрос
@footballer

Непонятное объяснение нового пула потоков в .NET — кто-нибудь может разъяснить?

Из статьи regfordev.blogspot.ru/2010/12/thread-pool.html
Абзац 1:
Новый пул потоков работает немного другим образом. Для каждого рабочего потока в пуле существует своя локальная очередь. Задача, которая попала в локальную очередь, может породить дочернюю и они размещаются в эту же локальную очередь. Также задачи выполняются в локальной очереди в LIFO (last-in-first-out) порядке, в отличие от пула в 3.5, где задачи из глобальной очереди выполняются рабочими потоками в FIFO (first-in-first-out) порядке. Так как только рабочий поток разгребает свою собственную кучу, вернее имеет доступ к ее началу (head), то на уровне локальной очереди не требуется никаких синхронизаций.

Абзац 2:
Когда рабочий поток видит что делать ему больше нечего, то есть его локальная очередь пустая, он пытается своровать задачу у другого рабочего потока. Но ворует он элементы с хвоста чужой локальной очереди.


Пытаюсь понять, что тут имеется ввиду. Предположим, что ситуация из абзаца 2 не случится (все потоки всегда будут заняты). То есть, как следует из абзаца 1, в этом случае, если мой код, выполняющий родительскую задачу (поток #1), создает новую параллельную дочернюю задачу через вызов Task.Run , то фактически дочерняя задача не запустится параллельно в другом потоке, а будет запущена в том же потоке #1, который поставил ее в очередь, уже после того, как поток #1 закончит выполнение родительской задачи? И по сути мы получим просто последовательное выполнение задач?

Если так, то тут же нет никакого параллельного выполнения задач. Для чего тогда тут использование Task.Run, когда можно тупо просто выполнить родительскую и дочернюю задачи последовательно друг другом в одном потоке?
Или предполагается, что ситуация, когда все потоки заняты, очень редкая, и фактически задача из Task.Run чаще всего будет запущена в отдельном потоке параллельно?

Или я вообще что-то не так понял? Объясните.
  • Вопрос задан
  • 219 просмотров
Подписаться 2 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 1
AlexanderYudakov
@AlexanderYudakov
C#, 1С, Android, TypeScript
Все просто.
Ребята поработали со старым механизмом и выяснили, что в условиях 100500 задач в секунду слишком много времени уходит на синхронизацию доступа потоков к одной единственной очереди задач.
Чтобы подобную проблему разрулить, решили в условиях перегрузок разделить глобальную очередь на несколько локальных - с тем, чтобы рабочий поток мог работать с этой локальной очередью без использования блокировки (соответственно, без простоя на ожидании этой блокировки).
Вот и все. Как только локальная очередь заканчивается, - работа идет с чужими локальными очередями и с глобальной очередью.
В общем, не парьтесь. Если у вас 10 задач в секунду, считайте ничего не поменялось.
А если 100500, то времени на ожидание блокировок будет уходить меньше. И производительность пула в этом случае возрастет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы