Go Язык Программирования Взаимное Параллельное Выполнение
У меня есть две параллельные процедуры go, как показано ниже,
Routine 1{
routine procedure
critical section{
}
routine procedure
}
Routine 2{
routine procedure
critical section{
}
routine procedure
}
Возможно ли с помощью некоторых встроенных функций go реализовать критический раздел ?
6 ответов:
Ваш вопрос:
У меня есть N параллельных подпрограмм go (все более или менее одинаковой цели). У каждого из них есть критический раздел. Прежде чем войти в критический раздел, каждая процедура просто выполняет некоторую работу по отправке сообщений. Когда он входит в критическую секцию, мне нужно, чтобы все остальные подпрограммы останавливали выполнение до тех пор, пока он не выйдет из критической секции. Возможно ли это с помощью любой библиотечной функции в GO?
То, о чем вы спрашиваете (чтобы заставить остановиться на всех других goroutines, в то время как один goroutine в критическом разделе) не является типичным в программах Go. Нет функции библиотеки, чтобы остановить все другие goroutines, поэтому вам нужно будет остановить их, разработав правильную синхронизацию между goroutines в вашей программе. Типичный сценарий заключается в том, что все goroutines (потенциально) запускаются одновременно, за исключением тех goroutines, которые каким-то образом заблокированы.
Для управления параллельным доступом к общему ресурсу в программе Go можно использовать каналы Go, пакет"sync", каналы или сеть подключение.Используя
sync.Mutex, код Go может выглядеть следующим образом (но, пожалуйста, имейте в виду, что, когда это возможно, программы Go должны предпочтительно использовать каналы Go вместо мьютексов):package main import "sync" var m sync.Mutex var wg sync.WaitGroup func routine1() { ... do something ... m.Lock() ... critical section (access the shared resource here) ... m.Unlock() ... do something ... wg.Done() } func routine2() { ... do something ... m.Lock() ... critical section (access the shared resource here) ... m.Unlock() ... do something ... wg.Done() } func main() { wg.Add(1); go routine1() wg.Add(1); go routine2() wg.Wait() }
Можно попробовать использовать буферный канал:
c := make(chan int, 2)Это буферизует данные, отправленные перед фактической отправкой.
Вы имеете в виду что-то вроде этого?
package main import "fmt" func ping(recv <-chan int, send chan<- int, end chan<- bool) { fmt.Println("ping") send <- 11 send <- 12 r1 := <-recv r2 := <-recv fmt.Println("ping", r1, r2) end <- true } func pong(recv <-chan int, send chan<- int, end chan<- bool) { fmt.Println("pong") r1 := <-recv r2 := <-recv send <- 21 send <- 22 fmt.Println("pong", r1, r2) end <- true } func main() { chEnd := make(chan bool) chPing := make(chan int, 2) chPong := make(chan int, 2) go ping(chPing, chPong, chEnd) go pong(chPong, chPing, chEnd) <-chEnd <-chEnd fmt.Println("end") }Вывод:
ping pong pong 11 12 ping 21 22 end
Я не думаю, что в go есть какая-либо библиотека для реализации критического раздела. Я думаю, что Arpssss просит библиотеку.
Возможны несколько подходов. Простой из них-использовать каналы, набранные для полного "события".
package main type int2 struct { a, b int } func Routine1(tx, rx chan int2) { var x, y int // ... tx <- int2{x, y} // ... z := <- rx // Two rx values in z.a, z.b // ... } func Routine2(rx, tx chan int2) { var x, y int // ... z := <- rx // Two rx values in z.a, z.b // ... tx <- int2{x, y} // ... } func main() { // ... tx, rx := make(chan int2), make(chan int2) go Routine1(tx, rx) go Routine2(rx, tx) // ... }
Вот основанный на канале эквивалент решения атома. Сделайте это перед запуском ваших goroutines:
doingFileModificationJobs := make(chan bool, 1) doingFileModificationJobs <- falseИ затем передайте этот канал в качестве параметра при запуске goroutines. Обратите внимание, что есть только один канал. Все горутины использовать этот же канал.
Это позволит вам использовать этот канал Как мьютекс. Замените ваш псевдокод,critical section{С
<-doingFileModicationJobsА затем замените соответствующую закрывающую скобку вашего псевдокода критической секции с,
Он прекрасно читается таким образом и более описателен, чем общие термины, такие как "мьютекс" или "критическая секция"."doingFileModications <- falseЭто сериализует ваши задания модификации файлов и гарантирует, что только одна goroutine в то время может быть делать их. Я думаю, что это общая концепция критического раздела, но если вам действительно нужно, чтобы другие goroutines остановились, даже если они просто выполняют работу по отправке сообщений, ну, это другая проблема.
Comments