goroutine值返回顺序

goroutine值返回顺序,go,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) } func测试(x int,c chan int){ 如果你想知道订单是什么

为什么以下代码总是返回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)
}
func测试(x int,c chan int){

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

本例使用函数闭包生成序列

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

由于序列计数器上有一个互斥锁,所以序列递增器在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)
        }
    }

}
主程序包
进口(
“fmt”
“同步”
)
使用顺序结构键入值{
v int
整数阶
}
变量(
mu-sync.Mutex
)
func orgami(x int,c chan value_,带顺序,f func()int){
v:=新值(带顺序的值)
v、 v=x
v、 顺序=f()

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

本例使用函数闭包生成序列

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

由于序列计数器上有一个互斥锁,所以序列递增器在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)
        }
    }

}
主程序包
进口(
“fmt”
“同步”
)
使用顺序结构键入值{
v int
整数阶
}
变量(
mu-sync.Mutex
)
func orgami(x int,c chan value_,带顺序,f func()int){
v:=新值(带顺序的值)
v、 v=x
v、 顺序=f()

c只是偶然的。在特定环境(例如操作系统、Go版本、GOMAXPROCS等)中,首先返回2,然后返回1的goroutines调度顺序不确定的可能性似乎更大可能您总是遵守相同的顺序,但您不能依赖于此。语言规范没有指定顺序。如果您需要特定的执行顺序,则必须通过显式同步来处理。这只是偶然的。首先返回2,然后返回1 goroutines的调度顺序的可能性似乎更大uled是不确定的。在特定环境中(如操作系统、Go版本、GOMAXPROCS等)可能你总是遵循相同的顺序,但你不能依赖于此。语言规范没有指定顺序。如果你需要特定的执行顺序,你必须通过显式同步来处理。顺序似乎是随机的。呼叫顺序是确定的,每个唯一的呼叫将有一个唯一的号码。但是授予每个调用的act序列号不一定是有序的,返回序列显然永远不会是有序的。如果您需要调用序列是有序的,那么在相同的go例程(主)中设置序列号。我将添加第二个版本来实现这一点-在走路线之前调用序列。顺序似乎是随机的。呼叫顺序是确定的,每个唯一的呼叫将有一个唯一的号码。但授予每个呼叫的确切序列号不一定是有序的,返回序列显然永远不会是有序的顺序。如果你需要调用顺序,那么在同一个go例程(主)中设置序列号。我将添加第二个版本来实现这一点-在go例程之前调用序列