Go 教程:通道和缓冲通道
Go tutorial: Channels and Buffered Channels
为什么当第二个值通过另一个 go routine 发送并且第一个值没有收到时,通道 c 没有缓冲?
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // send sum to c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c ,<-c// receive from c
fmt.Println(x,y ,x+y)
}
我期待的是一个错误-
fatal error: all goroutines are asleep - deadlock!
当缓冲区已满时出现块时会出现这种情况。由于通道 c 的大小为 1,因此发送第二个值应该会出现上述错误。
上面的代码发生了什么?
仅仅因为写入不能立即成功,只要有其他 goroutine 可以 运行.
就不会出现“死锁”错误
让我们想象一个调度模型,其中 go
函数立即启动 goroutine 并在让步给其他人之前尽可能多地向前推进。那么会发生这样的事情:
- 程序会为列表的前半部分调用
sum()
,计算和,并尝试将其写入通道,但由于没有监听器,它会阻塞。
- 程序会为列表的后半部分调用
sum()
,计算和,并尝试将其写入通道,但由于没有监听器,它会阻塞。
main()
将尝试从通道读取,唤醒之前的 goroutines 之一,并从中获取值。
main()
将尝试从通道读取,唤醒另一个阻塞的 goroutine,并从中获取值。
- 没有人再阻塞通道输入或输出,所有 goroutines(包括
main()
)都可以 运行 完成。
如果你假装 go
只是在后台安排一些事情并继续 运行 主 goroutine,你可以做同样的练习。重要的是,只要在同一个通道上有成对的读写,两者都会继续。
为什么当第二个值通过另一个 go routine 发送并且第一个值没有收到时,通道 c 没有缓冲?
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // send sum to c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c ,<-c// receive from c
fmt.Println(x,y ,x+y)
}
我期待的是一个错误-
fatal error: all goroutines are asleep - deadlock!
当缓冲区已满时出现块时会出现这种情况。由于通道 c 的大小为 1,因此发送第二个值应该会出现上述错误。
上面的代码发生了什么?
仅仅因为写入不能立即成功,只要有其他 goroutine 可以 运行.
就不会出现“死锁”错误让我们想象一个调度模型,其中 go
函数立即启动 goroutine 并在让步给其他人之前尽可能多地向前推进。那么会发生这样的事情:
- 程序会为列表的前半部分调用
sum()
,计算和,并尝试将其写入通道,但由于没有监听器,它会阻塞。 - 程序会为列表的后半部分调用
sum()
,计算和,并尝试将其写入通道,但由于没有监听器,它会阻塞。 main()
将尝试从通道读取,唤醒之前的 goroutines 之一,并从中获取值。main()
将尝试从通道读取,唤醒另一个阻塞的 goroutine,并从中获取值。- 没有人再阻塞通道输入或输出,所有 goroutines(包括
main()
)都可以 运行 完成。
如果你假装 go
只是在后台安排一些事情并继续 运行 主 goroutine,你可以做同样的练习。重要的是,只要在同一个通道上有成对的读写,两者都会继续。