2 回答

TA贡献1796条经验 获得超7个赞
首先,你的两个 goroutine 需要从chchannel 接收才能开始工作
for i<=10{
<-ch // wait until receive
fmt.Println(i)
i+=2
ch <- true
}
因此,您向通道发送一个值以ch使您的两个 goroutine 工作
func main() {
//...
ch <- true
//...
}
但这不会按预期工作,因为您的两个 goroutine 共享同一个ch通道。在执行时,它们ch <- true中main()只有一个可以接收、开始工作并将值发送回ch通道。
之后,两个 goroutine 不断从ch通道接收,开始工作并将值发送回通道
换句话说,两个 goroutine 使用chchannel相互发送和接收值
for i<=10 {
<-ch // receive when main() executed at first time, after that receive from another goroutine
fmt.Println(i) // start work
i+=2 //
ch <- true // return back to the channel, another goroutine will receive it
}
wg.Done()
但是问题是当一个goroutine退出时,剩下的goroutine在工作后仍然尝试发送到chchannel,但是没有receiver,这会导致死锁

TA贡献1851条经验 获得超4个赞
如果通道中没有空间,在通道上发送也会阻塞。如果您在通道中使用缓冲区,则发送可以工作。仅使用 1:
ch := make(chan bool, 1)
现在您可以发送数据了,它不会因为未满而阻塞 go 例程。如果您再次发送而不读取,那么它将阻止发送调用,因为再次没有空间并且之前的值仍然没有被消耗。
关于打印的顺序: goroutine 将首先开始并没有顺序,go lang 规范没有提到多个 goroutine 是否正在从一个通道接收数据,那么首先等待的是否真的首先得到它。因此,如果需要,您需要添加额外的同步来维护订单。这是订购同步的提示。
下面是修改后的打印代码,但我更喜欢不同的方法。检查上面链接中的 ping - pong 示例,其中使用了 2 个单独的通道而不是一个。
package main
import (
"fmt"
"sync"
)
func odd(wg *sync.WaitGroup, ch chan bool) {
defer wg.Done()
i := 1
for i <= 10 {
<-ch
fmt.Println(i)
i += 2
ch <- true
}
}
func even(wg *sync.WaitGroup, ch chan bool) {
defer wg.Done()
i := 2
for i <= 10 {
<-ch
fmt.Println(i)
i += 2
ch <- true
}
}
func main() {
var wg sync.WaitGroup
ch := make(chan bool, 1)
defer close(ch)
wg.Add(2)
go even(&wg, ch)
go odd(&wg, ch)
ch <- true
wg.Wait()
}
- 2 回答
- 0 关注
- 81 浏览
添加回答
举报