Вопрос

I have two concurrent go routines like below,

Routine 1{                                                  

routine procedure   

critical section{                                                     
}

routine procedure                        
} 

Routine 2{                                                  

routine procedure   

critical section{                                                     
}

routine procedure                       
} 

Is it possible by using some go inbuilt functions to implement critical section ?

Это было полезно?

Решение

Your question:

I have N concurrent go routines (all more or less same purpose). Each of those have a critical section. Before entering critical section, each routine just do some message sending job. When it enters critical section, I need all other routines must stop execution until it exits critical section. Is it possible by using any library function in GO?

What you are asking about (to force a stop on all other goroutines while one goroutine is in the critical section) is not typical in Go programs. There is no library function to stop all other goroutines, so you will need to stop them by designing proper synchronization among goroutines in your program. The typical scenario is for all goroutines to (potentially) run concurrently, except for those goroutines that are blocked somehow.

To control concurrent access to a shared resource in a Go program you can use Go channels, the "sync" package, pipes, or network connections.

Using sync.Mutex, the Go code may look like this (but please keep in mind that, whenever possible, Go programs should preferably use Go channels instead of mutexes):

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()
}

Другие советы

You could try using a buffered channel:

c := make(chan int, 2)

This will buffer the data sent before actually sending it.

Do you mean something like this?

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")
}

Output:

ping
pong
pong 11 12
ping 21 22
end

I don't think, there is any library in go to implement critical section. I think Arpssss is asking for a library.

Several approaches are possible. A simple one is to use channels typed for the full "event".

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)
        // ...
}

Here's a channel based equivalent to Atom's solution. Do this before starting your goroutines:

doingFileModificationJobs := make(chan bool, 1)
doingFileModificationJobs <- false

and then pass this channel as a parameter when you start goroutines. Note that there is just one channel. All goroutines use this same channel.

This will let you use this channel like a mutex. Replace your pseudocode,

critical section{

with

<-doingFileModicationJobs

and then replace the matching closing brace of your critical section pseudocode with,

doingFileModications <- false

It reads nicely that way and is more descriptive than general terms like "mutex" or "critical section."

This serializes your file modification jobs and ensures that only one goroutine at a time can be be doing them. I think this is the common concept of a critical section, but if you really need other goroutines to stop, even if they are just doing the message sending jobs, well, that's a different problem.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top