2013-06-06 3 views
1

Почему существует очередь Ready и Waiting для каждого объекта при использовании монитора? Если поток выполняется с объектом, просто введите следующий элемент в очередь ожидания. Очередь Ready кажется излишней.Ожидание очереди против очереди готовности

Контекст: .NET, более конкретно, класс монитора.

+0

Вы должны указать контекст. Вы что-то читали, когда пришли к этому вопросу? Если да, ссылку на него или повторить контекст здесь. –

+0

"in .NET" - Какой класс? Монитор? Что-то другое? – mbeckish

+0

Похоже, вы говорите о потоке Windows, а не о .NET. Просьба уточнить. –

ответ

2

Предполагая, что я правильно понял ваш вопрос, они служат для разных целей.

«Готовая» очередь предназначена для потоков, которые готовы к запуску, как только они смогут получить блокировку. Они просто ждут, чтобы приобрести замок. Это в основном используется для взаимного исключения, чтобы предотвратить одновременное использование двух потоков с использованием одного и того же ресурса.

«Ожидание» очередь для потоков, ожидающих определенного сигнала - а именно, пульсирующего монитора. Это часто используется для координации - например, в очереди производителей/потребителей, где, если очередь пуста, потребитель будет ждать, пока монитор не будет пульсирован, прежде чем он снова проверит очередь. Пока никто не производит, и никто не потребляет, ни один поток не владеет монитором - нет никакого ресурса в использовании. Но монитор используется для координирования потребителя с производителем.

+1

... или используйте чтение ума вуду, чтобы выяснить, что задает вопрос. –

+0

@TimothyShields: Ну, я искал «готовую очередь» и «очередь ожидания» и нашел этот вопрос: http://stackoverflow.com/questions/12121151/monitor-pulse-wait-unexpected-behaviour - я подозреваю, что это используя ту же терминологию. –

+0

Итак, вы говорите, что импульс будет уведомлять потребителя всякий раз, когда что-то будет готово, так что потребительская нить может делать другие вещи. Я не думаю, что это возможно, потому что импульс только уведомляет потоки, которые находятся в очереди ожидания, и эти потоки уже заблокированы, поэтому они ничего не могут сделать. – Yamcha

2

Очередь производителя/потребителя - действительно хороший пример использования для изучения класса Monitor.

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

Итак, предположим, что у вас есть потребительские потоки k, ожидающие обработки элементов в очереди. Другими словами, каждая нить реализует плотный цикл, постоянно пытается

  1. запрос, чтобы получить lock на очереди (это ставит вас в «готовом» очереди монитора).
  2. Как только вы получите блокировку, проверьте, есть ли в очереди какие-либо предметы. Если нет, у вас есть два варианта освобождения блокировки: a) Вызовите Monitor.Exit, а затем вызовите Monitor.Enter, чтобы поставить себя в очередь «готовой» очереди. b) Или вызовите Monitor.Wait и поставьте себя в очередь ожидания «Монитора».

Если вы выберете опцию «a», ваши потоки k будут тратить циклы ЦП, перемещаясь через готовую очередь снова и снова, не найдя никакой работы и начинать все сначала в задней части очереди.

Если вы выберете вариант «b», вы говорите: «Здесь нет ничего, что можно было бы сделать прямо сейчас, позвольте мне спать и разбудить меня, когда есть что-то делать».

С опцией «b», если очередь пуста, вы скоро найдете всех своих потребителей, спящих в очереди ожидания, и никакое время CPU не будет потрачено впустую.

Затем, когда производитель добавляет элемент в очередь, он вызывает Monitor.Pulse. Это пробуждает первый поток в очереди ожидания, который затем переходит в «готовую» очередь (которая также является передней частью очереди, если «готовая» очередь пуста).

Когда поток получает блокировку и потребляет этот элемент из очереди, он снова вызывает Monitor.Enter и переходит в конец «готовой» очереди.

См. this article для классической реализации очереди производителей/потребителей в .NET.

+0

Спасибо за подробный ответ, но ваша идея может быть легко реализована только с очередью ожидания (очередь спальных потоков). Почему вызов Monitor.Pulse не отменяет первый элемент очереди ожидания, т. Е. Зачем ему сначала идти в очередь на готовность? – Yamcha

+0

@ user1316459 - Предположим, что все потребители заняты, поскольку в очередь задач добавлено больше элементов (и все вызовы Monitor.Pulse не используются, потому что потребители уже готовы и заняты). Если есть только очередь ожидания, то, когда каждый пользователь заканчивает свою текущую задачу, он снова возвращается в режим ожидания в очереди ожидания, и для обработки новой работы не будет никаких пользователей. – mbeckish

+0

@ user1316459 - «но ваша идея может быть легко реализована только с очередью ожидания». Я приглашаю вас сделать это и сделать его общедоступным в блоге. Может быть, вы придумаете что-то новое. Или, может быть, вы этого не сделаете, но по пути вы получите глубокое понимание всех проблем. – mbeckish

Смежные вопросы