【发布时间】:2018-09-29 11:26:57
【问题描述】:
我想在通道中发送一个值以从主函数执行例程。发生的情况是哪个 goroutine 将首先从通道接收值。
package main
import (
"fmt"
"math/rand"
//"runtime"
"strconv"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
ch <- 1
receive(ch)
}
func receive(ch chan int){
for i := 0; i < 4; i++ {
// Create some threads
go func(i int) {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Println(<-ch)
}(i)
}
}
我当前的实现出错了。
致命错误:所有 goroutine 都处于休眠状态 - 死锁!
我怎么知道哪个 goroutine 将首先从通道接收值。其他 goroutine 会发生什么如果因为没有通道接收值而运行或抛出错误。因为其中一个已经收到了。
如果创建缓冲通道,我的代码可以工作。所以我不明白幕后发生了什么,这使它在创建如下所示的缓冲通道时起作用:
func main() {
var ch chan int
ch = make(chan int, 10)
ch <- 1
receive(ch)
}
如果我们看下面的代码。我可以看到我们可以直接通过通道发送值,不需要创建一个 goroutine 来通过一个通道向另一个 goroutine 发送一个值。
package main
import "fmt"
func main() {
// We'll iterate over 2 values in the `queue` channel.
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
for elem := range queue {
fmt.Println(elem)
}
}
那么我的代码有什么问题。为什么会造成死锁。
【问题讨论】:
-
ch <- 1阻塞直到<- c,receive永远不会被执行。 -
即使在编辑之后你仍然有同样的问题。
-
一种选择是为每个你想要发送值的 goroutine 创建一个通道。我不知道这是否是最好的选择。
-
阅读我的第一条评论,这就是您收到错误的原因。
receive永远不会被调用。要解决此问题,您可以在其自己的 goroutine 中发送到通道。例如。go func() { ch<-1 }(). -
顺序未指定,取决于调度程序的实现或在 Go 中处理 goroutine 的任何东西。这意味着来自第一个循环迭代的 goroutine 不一定是第一个被执行的。
标签: go