Дублирование очереди в TPL - PullRequest
3 голосов
/ 21 мая 2011

Я изучаю задачу параллельной библиотеки для .NET (TPL), пытаюсь понять, как она работает, я понимаю идею кражи работы, но не могу понять, почему мы используем дублирующую очередь и как она работает?

когда создается новая задача, кто указывает, какой поток должен ее взять и поместить в очередь задач?

ты можешь мне помочь?

1 Ответ

4 голосов
/ 22 мая 2011

Представьте, что вы внедряете TPL самостоятельно и используете обычные не дублирующие очереди на кражу работы. Таким образом, для каждой очереди у вас есть один поток, который выдвигается из хвоста очереди и выскакивает из него, и несколько потоков, которые могут быть взяты из заголовка очереди (в документе это называется воры). Поскольку вы хотите убедиться, что каждая задача, добавляемая в очередь, удаляется ровно один раз (либо путем нажатия, либо путем взятия), вы должны использовать блокировку в каждой из трех операций.

В каком-то смысле блокирование на push и pop кажется довольно расточительным, когда вы знаете, что только один поток будет использовать эти операции. Но вы ничего не можете с этим поделать, если хотите убедиться, что очередь ведет себя правильно.

Ваша библиотека работает, но вы понимаете, что часто случается так, что вы ожидаете задачу, которая еще даже не была запущена. Итак, как насчет синхронного запуска в текущем потоке? Вы можете сделать это, но проблема в том, что задача находится в некоторой очереди, и вы не можете безопасно и быстро удалить ее оттуда. Однако вы можете добавить в задачу флаг, указав его состояние и получив доступ к флагу в поточно-ориентированном режиме.

Таким образом, если вы в конце концов удалите задачу, вы не запустите ее, потому что знаете, что она уже запущена или даже завершена. Как насчет очереди? Мы сказали, что хотим убрать задачу из очереди ровно один раз. Но это больше не требуется: если мы удаляем какое-то задание дважды, это не имеет значения, потому что задание само по себе позаботится и фактически запустится только один раз.

Но это означает, что мы можем удалить блокировки из pop и push, что приведет к дублирующейся очереди, которая быстрее, чем обычная очередь для кражи работы, потому что она имеет более слабые требования: мы можем быть уверены, что каждая задача удаляется из нее как минимум один раз.

РЕДАКТИРОВАТЬ: реакции на вопросы:

удалить задачу, нажав ОК, но удалить задачу, поместив задачу в очередь!

Извините, это была ошибка, теперь исправлена. Это хлопает или берет.

случай 3 в примере с выдумкой на странице 6, не так ли?

Да.

почему? Я не могу понять эту проблему.

Проблема в том, что эта задача может находиться в очереди для любого потока или может выполняться в данный момент в любом потоке. Поэтому вам, по крайней мере, придется искать задачи, выполняющиеся в каждом потоке, используя блокировку для каждого потока. И каждый поток должен будет использовать блокировку всякий раз, когда он изменяет свою текущую задачу Если задача в данный момент не выполняется, вам нужно как минимум заблокировать очередь, из которой вы удаляете. Что также усложняет анализ поведения очереди: теперь все может исчезнуть из середины очереди.

Какова логическая связь между удалением блокировок из pop и push и дублированием очереди?

Когда вы снимаете блокировки, вы не можете быть полностью уверены, что задача удаляется ровно один раз. Может случиться так, что в очереди будет только одна задача, и два разных потока вызовут take и pop одновременно. Поскольку pop не использует блокировки, одна и та же задача удаляется дважды.

...