2

私は以下のような2つの同時goルーチンを持っています、

Routine 1{                                                  

routine procedure   

critical section{                                                     
}

routine procedure                        
} 

Routine 2{                                                  

routine procedure   

critical section{                                                     
}

routine procedure                       
} 

いくつかの組み込み関数を使用してクリティカルセクションを実装することは可能ですか?

4

6 に答える 6

3

あなたの質問:

私はN個の同時実行ルーチンを持っています(すべて多かれ少なかれ同じ目的です)。それぞれにクリティカル セクションがあります。クリティカル セクションに入る前に、各ルーチンはメッセージ送信ジョブを実行するだけです。クリティカル セクションに入ったら、クリティカル セクションを出るまで他のすべてのルーチンの実行を停止する必要があります。GOで任意のライブラリ関数を使用して可能ですか?

あなたが求めていること(1つのゴルーチンがクリティカルセクションにある間に他のすべてのゴルーチンを強制的に停止すること)は、Goプログラムでは一般的ではありません。他のすべてのゴルーチンを停止するライブラリ関数はないため、プログラム内のゴルーチン間で適切な同期を設計して停止する必要があります。典型的なシナリオは、何らかの理由でブロックされているゴルーチンを除いて、すべてのゴルーチンを (潜在的に) 同時に実行することです。

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()
}
于 2011-11-28T12:15:02.930 に答える
1

これは、Atomのソリューションに相当するチャネルベースです。あなたのgoroutinesを始める前にこれをしてください:

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

次に、ゴルーチンを開始するときに、このチャネルをパラメーターとして渡します。チャネルは1つだけであることに注意してください。すべてのゴルーチンはこの同じチャネルを使用します。

これにより、このチャネルをミューテックスのように使用できるようになります。擬似コードを置き換え、

critical section{

<-doingFileModicationJobs

次に、クリティカルセクションの擬似コードの一致する閉じ中括弧を次のように置き換えます。

doingFileModications <- false

それはそのようにうまく読み、「mutex」や「クリティカルセクション」のような一般的な用語よりも説明的です。

これにより、ファイル変更ジョブがシリアル化され、一度に1つのゴルーチンのみがそれらを実行できるようになります。これはクリティカルセクションの一般的な概念だと思いますが、メッセージ送信ジョブを実行しているだけでも、他のゴルーチンを停止する必要がある場合は、別の問題になります。

于 2011-11-28T21:26:20.687 に答える
1

いくつかのアプローチが可能です。簡単な方法は、完全な「イベント」用に入力されたチャネルを使用することです。

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)
        // ...
}
于 2011-11-27T17:19:57.987 に答える
1

バッファリングされたチャネルを使用してみることができます:

c := make(chan int, 2)

これにより、送信されたデータが実際に送信される前にバッファリングされます。

于 2011-11-27T16:11:06.147 に答える
1

このようなことを意味しますか?

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
于 2011-11-27T16:50:54.907 に答える
1

クリティカルセクションを実装するためのライブラリはありません。Arpssss がライブラリを求めていると思います。

于 2011-11-27T17:03:15.913 に答える