4

go 言語で複数のチャネルが同時に準備されているかどうかを確認できるかどうかを知りたいです。

これは、私がやろうとしていることのやや不自然な例です。(実際の理由は、ペトリネットを go でネイティブに実装できるかどうかを確認するためです)

package main

import "fmt"

func mynet(a, b, c, d <-chan int, res chan<- int) {
    for {
        select {
        case v1, v2 := <-a, <-b:
            res <- v1+v2
        case v1, v2 := <-c, <-d:
            res <- v1-v2
        }
    }
}

func main() {
        a := make(chan int)
        b := make(chan int)
        c := make(chan int)
        d := make(chan int)
        res := make(chan int, 10)
        go mynet(a, b, c, d, res)

        a <- 5
        c <- 5
        d <- 7
        b <- 7
        fmt.Println(<-res)
        fmt.Println(<-res)
}

これは、示されているようにコンパイルされません。1 つのチャネルをチェックするだけでコンパイルすることができますが、そのチャネルの準備ができていて、もう 1 つのチャネルの準備ができていない場合、自明にデッドロックする可能性があります。

package main

import "fmt"

func mynet(a, b, c, d <-chan int, res chan<- int) {
    for {
        select {
        case v1 := <-a:
            v2 := <-b
            res <- v1+v2
        case v1 := <-c:
            v2 := <-d
            res <- v1-v2
        }
    }
}

func main() {
        a := make(chan int)
        b := make(chan int)
        c := make(chan int)
        d := make(chan int)
        res := make(chan int, 10)
        go mynet(a, b, c, d, res)

        a <- 5
        c <- 5
        d <- 7
        //a <- 5
        b <- 7
        fmt.Println(<-res)
        fmt.Println(<-res)
}

一般的なケースでは、複数のケースが同じチャネルで待機している可能性があります。

case v1, v2 := <-a, <-b:
...
case v1, v2 := <-a, <-c:
...

そのため、チャネル a で値の準備ができている場合は、どちらのブランチにもコミットできません。すべての値の準備ができている場合のみです。

4

2 に答える 2

0

蓄積している 2 つの異なるペアの個々のチャネルが機能する場合があります。

package main

import "fmt"

func mynetPlus(a, b <-chan int, res chan<- int) {
    for {
        select {
        case v1 := <-a:
            v2 := <-b
            res <- v1 + v2
        case v2 := <-b:
            v1 := <-a
            res <- v1 + v2
        }
    }
}

func mynetMinus(c, d <-chan int, res chan<- int) {
    for {
        select {
        case v1 := <-c:
            v2 := <-d
            res <- v1 + v2
        case v2 := <-d:
            v1 := <-c
            res <- v1 + v2
        }
    }
}

func main() {
    a := make(chan int)
    b := make(chan int)
    c := make(chan int)
    d := make(chan int)
    res := make(chan int, 10)
    go mynetPlus(a, b, res)
    go mynetMinus(c, d, res)

    a <- 5
    c <- 5
    d <- 7
    //a <- 5
    b <- 7
    fmt.Println(<-res)
    fmt.Println(<-res)
}
于 2015-07-29T17:59:42.463 に答える