在 for 循环中生成 goroutine 时出现死锁
Deadlock when spawning goroutine in a for loop
考虑以下 go playground
package main
import "fmt"
func main() {
var chan_array [2]chan int
chan1 := make(chan int)
chan2 := make(chan int)
chan_array[0] = chan1
chan_array[1] = chan2
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i]:
if (x == 0) {
return
}
fmt.Println(x)
}
}()
}
chan1<- 1
chan2<- 2
chan1<- 0
chan2<- 0
}
上面的代码试图创建 2 个 运行ning goroutines 来监听通道以发出打印或关闭信号。
但是上面的代码运行陷入了死锁。
我不太清楚为什么
谁能指出我的错误?
谢谢
当 goroutines 运行 时,变量 i
已经递增。而是将其作为函数参数传递。
事实上,永远不要依赖 goroutine 中函数闭包中的变量。太不靠谱了
存在一些问题:
当chan_array[i-1]
运行时i
的值是多少:
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i-1]:
if x == 0 {
return
}
fmt.Println(x)
}
}()
}
试试这个:
for i := 0; i < 2; i++ {
go func(i int) {
select {
case x := <-chan_array[i]:
if x == 0 {
return
}
fmt.Println(x)
}
}(i)
}
让我们简化您的代码(进行一些更正):
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
有了这些:
chan1 <- 1
chan2 <- 2
致命错误:
all goroutines are asleep - deadlock!
你的 goroutines 完成了,没有 goroutines 监听 chan1
和 chan1
这里:
chan1 <- 0
chan2 <- 0
您更正后的工作示例代码是:
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
for {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
}
输出:
1
2
考虑以下 go playground
package main
import "fmt"
func main() {
var chan_array [2]chan int
chan1 := make(chan int)
chan2 := make(chan int)
chan_array[0] = chan1
chan_array[1] = chan2
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i]:
if (x == 0) {
return
}
fmt.Println(x)
}
}()
}
chan1<- 1
chan2<- 2
chan1<- 0
chan2<- 0
}
上面的代码试图创建 2 个 运行ning goroutines 来监听通道以发出打印或关闭信号。
但是上面的代码运行陷入了死锁。
我不太清楚为什么
谁能指出我的错误?
谢谢
当 goroutines 运行 时,变量 i
已经递增。而是将其作为函数参数传递。
事实上,永远不要依赖 goroutine 中函数闭包中的变量。太不靠谱了
存在一些问题:
当chan_array[i-1]
运行时i
的值是多少:
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i-1]:
if x == 0 {
return
}
fmt.Println(x)
}
}()
}
试试这个:
for i := 0; i < 2; i++ {
go func(i int) {
select {
case x := <-chan_array[i]:
if x == 0 {
return
}
fmt.Println(x)
}
}(i)
}
让我们简化您的代码(进行一些更正):
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
有了这些:
chan1 <- 1
chan2 <- 2
致命错误:
all goroutines are asleep - deadlock!
你的 goroutines 完成了,没有 goroutines 监听 chan1
和 chan1
这里:
chan1 <- 0
chan2 <- 0
您更正后的工作示例代码是:
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
for {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
}
输出:
1
2