Go Язык Программирования Взаимное Параллельное Выполнение



У меня есть две параллельные процедуры go, как показано ниже,



Routine 1{                                                  

routine procedure

critical section{
}

routine procedure
}

Routine 2{

routine procedure

critical section{
}

routine procedure
}


Возможно ли с помощью некоторых встроенных функций go реализовать критический раздел ?

592   6  

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

    Ничего не найдено.