gpt4 book ai didi

go - 这里有资源泄漏吗?

转载 作者:IT王子 更新时间:2023-10-29 01:23:30 28 4
gpt4 key购买 nike

func First(query string, replicas ...Search) Result {
c := make(chan Result)
searchReplica := func(i int) {
c <- replicas[i](query)
}
for i := range replicas {
go searchReplica(i)
}
return <-c
}

这个函数来自 Rob Pike 在 2012 年关于 go concurrency patterns 的幻灯片。我认为这个函数有资源泄漏。由于在 channel c 上发生第一个发送和接收对后函数返回,其他 go 例程尝试在 channel c 上发送。所以这里存在资源泄漏。任何人都知道 golang 可以证实这一点吗?以及如何使用哪种 golang 工具检测此泄漏?

最佳答案

是的,你是对的(供引用,这里是 link to the slide )。在上面的代码中,只有一个启动的 goroutine 将终止,其余的将挂起尝试在 channel c 上发送。 .

细节:

  • c是一个无缓冲 channel
  • return 中只有一个接收操作声明
  • replicas 的每个元素启动一个新的 goroutine
  • 每个启动的 goroutine 在 channel 上发送一个值 c
  • 因为只有 1 个来自它的接收,一个 goroutine 将能够在其上发送一个值,其余的将永远阻塞

注意,取决于replicas的元素个数| (即 len(replicas) ):

  • 如果是 0 : First()会永远阻塞(没有人在 c 上发送任何东西)
  • 如果是 1 : 会按预期工作
  • 如果是 > 1 : 然后它会泄漏资源

以下修改版本不会泄漏 goroutines,通过使用非阻塞发送(在 selectdefault 分支的帮助下):

searchReplica := func(i int) {
select {
case c <- replicas[i](query):
default:
}
}

准备好结果的第一个 goroutine 将把它发送到 channel c这将由运行的 goroutine 接收 First() , 在 return陈述。所有其他 goroutines 当他们有结果时将尝试在 channel 上发送,并且“看到”它没有准备好(发送会阻塞因为没有人准备好从它接收),default分支将被选择,因此 goroutine 将正常结束。

另一种解决方法是使用缓冲 channel :

c := make(chan Result, len(replicas))

这样发送操作就不会阻塞。当然,只会从 channel 接收并返回一个(第一个发送的)值。

请注意,如果 len(replicas),具有上述任何修复的解决方案仍会阻塞是0 .为避免这种情况,First()应该明确检查这一点,例如:

func First(query string, replicas ...Search) Result {
if len(replicas) == 0 {
return Result{}
}
// ...rest of the code...
}

一些检测泄漏的工具/资源:

关于go - 这里有资源泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49648380/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com