3 回答

TA贡献1869条经验 获得超4个赞
用于取消,如链接文章中所示。close()
有问题的代码不能保证工作。下面是它失败的场景:
一个戈鲁丁已准备好从 接收。所有其他戈鲁丁人都在其他地方忙碌。
exit
main 发送的值由准备好的戈鲁廷接收。
该戈鲁廷向 接收的值发送一个值。
exit
main()
其他戈鲁廷不会退出,因为没有更多的值被发送到 。请参阅此使用时间的游乐场示例。渗漏以诱导问题场景。exit
为什么总是在go例程中进行接收,并且只有当所有例程都完成时,才会执行带有注释“//Final Exit”的通道接收?
该程序的执行方式就好像通道维护着一个有序的等待戈鲁丁队列,但规范中没有任何内容可以保证该行为。即使通道具有有序队列,如果 goroutine 正在执行某些操作而不是等待从 接收,则程序也可能会遇到上述情况。exit

TA贡献1818条经验 获得超7个赞
如果您注意到程序的输出
In go routine 6
In go routine 0
In go routine 7
.
.
Exit received from 6
Exit received from 0
Exit received from 7
.
.
Final exit
它们以相同(或几乎相同)的顺序被调用,这些顺序与它们的启动方式相同。如果您的 Go 例程都不繁忙,则将使用第一个注册的例程。这只是运行时的实现,我不会指望这种行为。
您的最终出口是最后一个要收听的通道,因此最后使用它。
如果删除时间。循环后睡觉,您的最终出口几乎会立即被调用,并且您的大多数go例程都不会收到退出信号
输出与时间输出。睡眠(在跑步之间会非常多)
In go routine 0
Exit received from 0
In go routine 1
In go routine 2
In go routine 3
In go routine 4
In go routine 5
In go routine 6
In go routine 7
In go routine 14
In go routine 15
In go routine 16
In go routine 17
In go routine 18
In go routine 19
Final exit

TA贡献1811条经验 获得超5个赞
请考虑此轻微修改。
package main
import (
"fmt"
)
func main() {
var exit chan int = make(chan int)
var workers = 20
for i := 0; i < workers; i++ {
go func(instance int) {
fmt.Println("In go routine ", instance)
for {
select {
case i := <-exit:
fmt.Println("Exit", i, "received from ", instance)
exit <- i-1
return
}
}
}(i)
}
exit <- workers
fmt.Println("Final exit:", <-exit)
}
在这里,我做了3件事:首先,为了简洁起见,我删除了未使用的频道。其次,我消除了睡眠。第三,我将通道更改为每次通过都会递减的通道。如果我传入工作人员的数量,则除“最终”消息以外的任何值都表示工作人员被丢弃。exitint0
下面是一个运行示例:
% go run t.go
In go routine 8
In go routine 5
In go routine 0
In go routine 2
Exit 20 received from 8
Exit 19 received from 5
Final exit: 18
In go routine 13
当呼叫时,直到睡眠结束才会安排。其他哥鲁丁都有这个时间来设置他们的频道阅读器。我只能假设,因为我在任何地方都找不到它,频道读者很可能在大致的时间顺序错误中排队 - 因此,保证读者是最后一个。maintime.Sleepsleepmain
如果这是一致的行为,那肯定是不可靠的。
请参阅在一个频道上收听多个戈鲁丁,以获取有关此内容的更多想法。
- 3 回答
- 0 关注
- 65 浏览
添加回答
举报