Проблема с обоюдным выполнением подпрограмм Go - PullRequest
0 голосов
/ 04 декабря 2011

В моем коде есть три одновременных подпрограммы.Я пытаюсь дать краткий обзор моего кода:

Routine 1 {
do something

*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 2 {
do something

*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 3 {
do something

*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*

do something
}

main {
routine1
routine2
routine3
}

Я хочу, чтобы, пока коды между двумя что-то делали (коды между двумя звездочками) выполнялись, поток управления не должен переходить к другим процедурам go,Например, когда рутина 1 выполняет события между двумя звездами (события отправки и печати), рутина 2 и 3 должна быть заблокирована (означает, что последовательность выполнения не переходит к рутине 2 или 3 из рутины 1). После завершения последнего события печати,Поток выполнения может перейти к процедуре 2 или 3. Может ли кто-нибудь помочь мне, уточнив, как мне этого добиться?Возможно ли реализовать вышеуказанную спецификацию с помощью WaitGroup?Кто-нибудь может показать мне, приведя простой пример, как реализовать указанный выше пример с помощью WaitGroup.Спасибо.

Примечание: может быть, это повторный вопрос этого .Я попытался с помощью этого механизма синхронизации синхронизировать, однако, может быть потому, что у меня большой код, поэтому я не мог правильно поставить блокировку разблокировки, и это создает ситуацию взаимоблокировки (или может быть мой метод is ошибка при создании ).Может ли кто-нибудь помочь мне с помощью простой процедуры, поэтому я могу достичь этого. Я привожу простой пример моего кода здесь где Здесь я хочу поместить два отпечатка и отправить событие в мьютекс (для подпрограммы 1), таким образом подпрограмма 2 не может его прервать.Можете ли вы помочь мне, как это возможно.Дано одно возможное решение, http://play.golang.org/p/-uoQSqBJKS, которое дает ошибку.

Ответы [ 2 ]

3 голосов
/ 04 декабря 2011

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

Еще одна подсказка может заключаться в подозрительной смеси явной синхронизации и канала связи. Это не значит, что дизайн обязательно сломан. Это просто не происходит в типичном / простом случае. Еще раз, ваша проблема может быть нетипичной / нетривиальной.

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

Попытайтесь думать о своих горутинах как о независимо действующих агентах, которые:

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

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

3 голосов
/ 04 декабря 2011

Почему вы хотите это сделать?

Проблема взаимоблокировки в том, что если вы не разрешаете планировать другие программы, отправка вашего канала не может быть продолжена, если нет буферизации.Каналы Go имеют конечную буферизацию, так что вы в конечном итоге получите состояние гонки при сливе, прежде чем они будут отправлены, пока они заполнены.Вы можете ввести бесконечную буферизацию или поместить каждую посылку в свою собственную программу, но опять-таки все сводится к следующему: почему вы пытаетесь это сделать;что вы пытаетесь достичь?

Другое дело: если вы хотите обеспечить взаимное исключение трех наборов кода между * s, тогда да, вы можете использовать взаимные исключения.Если вы хотите, чтобы код no прерывал ваш блок, независимо от того, где он был приостановлен, вам может потребоваться использовать runtime.LockOSThread и runtime.UnlockOSThread.Это довольно низкий уровень, и вам нужно знать, что вы делаете, и они нужны редко.Если вы не хотите, чтобы другие подпрограммы выполнялись, вам понадобится runtime.GOMAXPROCS (1), который в настоящее время используется по умолчанию.

...