goroutine 值返回顺序

标签 go goroutine

<分区>

为什么下面的代码总是返回 2,1,而不是 1,2。

func test(x int, c chan int) {
   c <- x
}

func main() {
    c := make(chan int)
    go test(1, c)
    go test(2, c)
    x, y := <-c, <-c // receive from c
    fmt.Println(x, y)
}

最佳答案

如果你想知道顺序是什么,那就让你的程序包含顺序信息

这个例子使用一个函数闭包来生成一个序列

channel 返回两个数字的结构,其中一个是序列号

序列增量器在 go 例程中应该是安全的,因为序列计数器上有互斥锁

package main

import (
    "fmt"
    "sync"
)

type value_with_order struct {
    v     int
    order int
}

var (
    mu sync.Mutex
)

func orgami(x int, c chan value_with_order, f func() int) {
    v := new(value_with_order)
    v.v = x
    v.order = f()
    c <- *v
}
func seq() func() int {
    i := 0
    return func() int {
        mu.Lock()
        defer mu.Unlock()
        i++
        return i
    }
}

func main() {

    c := make(chan value_with_order)
    sequencer := seq()
    for n := 0; n < 10; n++ {
        go orgami(1, c, sequencer)
        go orgami(2, c, sequencer)
        go orgami(3, c, sequencer)
    }
    received := 0
    for q := range c {
        fmt.Printf("%v\n", q)
        received++
        if received == 30 {
            close(c)
        }
    }

}

第二个版本,从主循环调用序列,使序列号按照函数调用的顺序出现

package main

import (
    "fmt"
    "sync"
)

type value_with_order struct {
    v     int
    order int
}

var (
    mu sync.Mutex
)

func orgami(x int, c chan value_with_order, seqno int) {
    v := new(value_with_order)
    v.v = x
    v.order = seqno
    c <- *v
}
func seq() func() int {
    i := 0
    return func() int {
        mu.Lock()
        defer mu.Unlock()
        i++
        return i
    }
}

func main() {

    c := make(chan value_with_order)
    sequencer := seq()
    for n := 0; n < 10; n++ {

        go orgami(1, c, sequencer())
        go orgami(2, c, sequencer())
        go orgami(3, c, sequencer())
    }
    received := 0
    for q := range c {
        fmt.Printf("%v\n", q)
        received++
        if received == 30 {
            close(c)
        }
    }

}

关于goroutine 值返回顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50771812/

相关文章:

go - 如何使用 channel 通知 goroutine 正确退出

反射式没有方法

android - 在 Android 上使用网络

go - 基本 goroutine 和 channel 模式 : multiple goroutines for one channel

go - 在收听和服务时使用缓冲 channel 处理错误

Go 扫描缓冲区有时会挂起

windows - golang 中的 GetSpecialFolder 等价物

go - 为什么这段关于golang goruntine运行顺序的代码首先是 "2"

go - 为什么所有的 goroutines 都在 sleep ?

go - golang 中的生产者消费者