Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么goroutines行政命令在两次运行之间是相同的_Go_Concurrency_Goroutine - Fatal编程技术网

为什么goroutines行政命令在两次运行之间是相同的

为什么goroutines行政命令在两次运行之间是相同的,go,concurrency,goroutine,Go,Concurrency,Goroutine,我有一个简单的围棋程序,其中有两个消费者频道同时从一个制作人那里读取数据,如下所示: package main import "fmt" func main() { producer := make(chan int) wait := make(chan int) go func() { for i := 0; i < 1000; i++ { producer <- i } close

我有一个简单的围棋程序,其中有两个消费者频道同时从一个制作人那里读取数据,如下所示:

package main

import "fmt"

func main() {
    producer := make(chan int)
    wait := make(chan int)
    go func() {
        for i := 0; i < 1000; i++ {
            producer <- i
        }
        close(producer)
        wait <- 1
    }()

    go func() {
        count := 0
        for _ = range producer {
            count++
        }
        fmt.Printf("Consumer 1: %i\n", count)
    }()

    go func() {
        count := 0
        for _ = range producer {
            count++
        }
        fmt.Printf("Consumer 2: %i\n", count)
    }()
    <-wait
}
它在多次运行之间保持不变。有人能为我解释一下这种行为吗

环境

go version go1.4.2 darwin/amd64
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/usr/local/go/:/Users/victor/Dropbox/projects/go/"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.4.2/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.4.2/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"

Go编程语言规范中未定义Go goroutine调度算法。它是未定义的,因此它依赖于实现和版本。Go的当前实现使用协作调度方案。协作调度方案依赖于goroutines来执行不时地向调度器屈服的操作。调度程序代码位于包运行时中

该程序取决于通道操作

该程序还取决于硬件(例如,CPU数量)、操作系统和其他正在运行的程序

您的代码不应该期望goroutine调度中出现特定的分发

Go 1.4默认为GOMAXPROCS(1);对于Go 1.5及更高版本,它默认为NumCPU()

我已经修改了您的程序,以修复bug(附加等待语句),显示诊断信息,并在某些点向调度程序(Gosched())屈服。现在,该程序将在Go 1.6(devel-tip)、NumCPU()==8、GOMAXPROCS(8)和Go 1.5.1、NumCPU()==1、GOMAXPROCS(1)上密切复制您的结果。在紧循环中的某些点而不是在其他点向goroutine调度程序屈服,这是复制结果的关键

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println(runtime.Version())
    fmt.Println(runtime.NumCPU())
    fmt.Println(runtime.GOMAXPROCS(0))
    producer := make(chan int, 100)
    wait := make(chan int, 100)
    go func() {
        for i := 0; i < 1000; i++ {
            producer <- i
            runtime.Gosched()
        }
        close(producer)
        wait <- 1
    }()
    go func() {
        count := 0
        for _ = range producer {
            count++
        }
        fmt.Printf("Consumer 1: %d\n", count)
        wait <- 1
    }()
    go func() {
        count := 0
        for _ = range producer {
            count++
            runtime.Gosched()
        }
        fmt.Printf("Consumer 2: %d\n", count)
        wait <- 1
    }()
    <-wait
    <-wait
    <-wait
}
游乐场:

为便于比较,不作让步:

> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 81
Consumer 2: 919
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 123
Consumer 2: 877
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 81
Consumer 2: 919
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 2: 673
Consumer 1: 327
游乐场:


我没有输出。您从
go version
go env
的输出是什么。我刚刚用您请求的信息更新了问题,所以我猜我的程序运行时使用的是1个CPU,2个使用者什么也不做,而不是增加计数器,速度太快,因此使用者1可能会在使用者2参与之前完成任务?你觉得@peterSO怎么样?我明白了,但我还是不明白为什么我的消费者总是667和333。即使使用1个CPU,也必须有一个明确的解释。@vutran:请参阅我修改后的答案。谢谢@peterSO,您的答案非常有用。我如何私下联系您?
> go run yield.go
8
8
Consumer 1: 668
Consumer 2: 332
> go run yield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 2: 336
Consumer 1: 664
> go run yield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 2: 333
Consumer 1: 667
>
go1.5.1
1
1
Consumer 1: 674
Consumer 2: 326
go1.5.1
1
1
Consumer 1: 674
Consumer 2: 326
go1.5.1
1
1
Consumer 1: 674
Consumer 2: 326
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 81
Consumer 2: 919
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 123
Consumer 2: 877
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 1: 81
Consumer 2: 919
> go run noyield.go
devel +54b4b94 Sat Feb 6 23:33:23 2016 +0000
8
8
Consumer 2: 673
Consumer 1: 327
go1.5.1
1
1
Consumer 1: 100
Consumer 2: 900
go1.5.1
1
1
Consumer 1: 100
Consumer 2: 900
go1.5.1
1
1
Consumer 1: 100
Consumer 2: 900