Заставить поток ждать условие, но позволить потоку оставаться работоспособным во время ожидания или прослушивания сигнала - PullRequest
0 голосов
/ 19 декабря 2018

Учитывая ситуацию, когда поток A должен был отправить работу потоку B, существует ли какой-либо механизм синхронизации, который позволяет потоку A не возвращать , но оставаться пригодным для других задач , пока поток B не будет выполнен,какой тогда поток А может вернуть?

Это не зависит от языка, но простой язык c был бы отличным выбором в ответ на это.

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

Обратите внимание This is a made up hypothetical situation, что меня интересует. Я не ищу решенияк существующей проблеме, поэтому альтернативные параллельные решения совершенно бессмысленны.У меня нет кода для этого, и если бы я был в нем, я мог бы придумать несколько альтернативных решений для разработки кода, чтобы избежать этой настройки.Я просто хочу знать, можно ли каким-то образом использовать поток во время ожидания сигнала от другого потока и какой механизм синхронизации использовать для этого.


ОБНОВЛЕНИЕ

Как я уже упоминал выше, я знаю, как синхронизировать потоки и т. Д. Меня интересует только ситуация, которую я представил здесь.Мьютексы, семафоры и блокировки всех видов механизмов синхронизируют доступ к ресурсам, синхронизируют порядок событий, синхронизируют все виды одновременно возникающих проблем, да.Но меня не интересует, как это сделать правильно.У меня просто есть эта выдуманная ситуация, и я хочу знать, можно ли решить ее с помощью механизма, описанного ранее.


ОБНОВЛЕНИЕ 2

Кажется, я открыл портал для людей, которые считают себя экспертами по параллелизму, чтобы телепортироваться и случайно читать лекции о том, как, по их мнению, остальной мир не знает, как работают потоки.Я просто спросил, есть ли механизм для этой ситуации, не решение проблемы, не «правильный способ синхронизации», не лучший способ сделать это.Я уже знаю, что я буду делать, и никогда не буду в этой выдуманной ситуации. Это просто гипотетически .

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

После долгих исследований, размышлений и обзора я пришел к выводу, что все равно, что спросить:

Если у меня есть возможность калькулятора, просто введите последовательность из 5 цифр и автоматически получитеих сумма на экране.

Нет, такой режим не готов.Но я все еще могу получить сумму несколькими дополнительными щелчками, используя кнопку «плюс» и, в конце концов, кнопку «равно».

Если бы я действительно хотел thread, который может продолжаться при прослушивании какого-либо условия, я мог бы легкореализовать персональный класс или объект вокруг OS / kernel / SDK thread или чего-либо еще и использовать это.

• So at a low level, my answer is no, there is no such mechanism •

Если поток ожидаеттогда оно ждет.Если он может продолжить выполнение, то это не «ожидание» в смысле параллелизма ожидания.В противном случае был бы какой-то другой термин для этого состояния (Alert Waiting, кто-нибудь?).Это не означает, что это невозможно, просто не с одним простым предопределенным механизмом низкого уровня, похожим на мьютекс или семафор и т. Д. Можно обернуть требуемую функциональность в некоторый класс или объект и т. Д.

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

0 голосов
/ 19 декабря 2018

Вы неправильно понимаете, как обычно используются мьютексы.

Если вы хотите выполнить какую-то работу, вы приобретаете мьютекс, чтобы выяснить, какую работу вам нужно выполнить.Вы делаете это, потому что «какая работа вам нужна» распределяется между потоком, который решает, какую работу нужно выполнить, и потоком, который будет выполнять эту работу.Но затем вы освобождаете мьютекс, который защищает «какую работу вам нужно делать», пока вы выполняете работу.

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

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

Если вы держите мьютексы так долго, что вам вообще не нужно ждать, пока онибыть освобожденным, вы либо делаете что-то не так, либо используете мьютексы очень нетипичным способом.

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

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

Если вы рассматриваете любой случай, когда один поток может замедлить другой поток для «ожидания», то вы никогда не сможете избежать ожидания.Все, что должно произойти, это то, что один поток обращается к памяти, и это может замедлить работу другого потока.Так что вы делаете, никогда не обращаетесь к памяти?

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

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

Обновление:

Например, рассмотрим некоторый код с мьютексом и логическим значением.Логическое значение указывает, выполнена ли работа.Процесс «назначить работу» выглядит следующим образом:

  1. Создайте рабочий объект с мьютексом и логическим значением.Установите для логического значения значение false.
  2. Отправьте поток для работы с этим объектом.

Поток "do work" выглядит следующим образом:

  1. DoРабота.(Мьютекс здесь не удерживается.)
  2. Получить мьютекс.
  3. Установить логическое значение true.
  4. Отменить мьютекс.

""работа выполнена "поток выглядит следующим образом:

  1. получение мьютекса.
  2. копирование логического значения.
  3. освобождение мьютекса.
  4. просмотр скопированного значения.

Это позволяет одному потоку выполнять работу, а другому потоку проверять, выполняется ли работа в любое время, когда она этого захочет, при выполнении других задач.Единственный случай, когда один поток ожидает другого, - это случай «один на миллион», когда поток, который должен проверить, выполнена ли работа, выполняет проверку в тот момент, когда работа только что завершилась.Даже в этом случае он обычно блокируется менее чем на микросекунду, так как потоку, который содержит мьютекс, нужно только установить один логический тип и освободить мьютекс.И даже если это вас беспокоит, большинство мьютексов имеют неблокирующую функцию «попытаться заблокировать» (которую вы использовали бы в потоке «проверьте, если работа выполнена», чтобы поток проверки никогда не блокировался).

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

...