go - 检查准备就绪的同步 channel

标签 go channel petri-net

我想知道 go 语言是否允许检查多个 channel 是否准备就绪同时

这是我正在尝试做的一个有点人为的例子。 (实际原因是看我能不能在go中原生实现petrinets)

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

这不会像显示的那样编译。它可以通过仅检查一个 channel 来编译,但如果该 channel 准备就绪但另一个 channel 未准备好,它可能会死锁。

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

在一般情况下,我可能有多个案例在同一个 channel 上等待,例如

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

所以当 channel a 上的值准备就绪时,我不能提交到任何一个分支:只有当所有值都准备好时。

最佳答案

您不能同时选择多个 channel 。您可以做的是实现扇入模式,以从多个 channel 整合您的值(value)观。

基于您的代码的粗略示例可能如下所示:

func collect(ret chan []int, chans ...<-chan int) {
    ints := make([]int, len(chans))
    for i, c := range chans {
        ints[i] = <-c
    }
    ret <- ints
}

func mynet(a, b, c, d <-chan int, res chan<- int) {
    set1 := make(chan []int)
    set2 := make(chan []int)
    go collect(set1, a, b)
    go collect(set2, c, d)
    for {
        select {
        case vs := <-set1:
            res <- vs[0] + vs[1]
        case vs := <-set2:
            res <- vs[0] + vs[1]
        }
    }
}

关于go - 检查准备就绪的同步 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31707158/

相关文章:

go - 如何在 golang 的所有包中访问全局常量?

go - 如何从 go routine 中退出外循环?

go - 我怎么可能有基于接收者的不同返回类型的方法?

golang反射初始化满足接口(interface)的结构

asynchronous - 在 Go 中使用 Channels 实现 Promise

synchronization - 在 channel 上阻塞发送一个错误的同步范例以及为什么

go - 是否关闭 channel 阻塞直到接收者读取它

java - 无循环死锁

concurrency - 是否有建模/模拟软件并发性的工具?