当前位置: 首页 > 知识库问答 >
问题:

练习解决方案中的内存泄漏:等效二叉树?

濮阳浩穰
2023-03-14

(https://github.com/golang/tour/blob/master/solutions/binarytrees_quit.go)练习:等价二叉树假设我们有两个简单的等价二叉树“1 3 5”和“2 3 5”。当两个goroutine“Walk”同时在叶“1”和“2”处行走时,

if v1 != v2 {
    return false
}

函数中的条件相同将为真

关闭(退出)

会跑。

func walkImpl(t *tree.Tree, ch, quit chan int) {
    if t == nil {
        return
    }
    walkImpl(t.Left, ch, quit)
    select {
    case ch <- t.Value:
        // Value successfully sent.
    case <-quit:
        return
    }
    walkImpl(t.Right, ch, quit)
}

通道“quit”将接收消息,并执行select语句的第二种情况。然后它将返回到上层函数“walkinpl”,并继续运行最后一行walkinpl(t.Right,ch,quit)。那么,在这种情况下是否存在goroutine泄漏,导致通道“quit”已被读取,无法在上层再次读取?函数“Walk”也不能返回到“close”处理程序。

共有1个答案

鄢承运
2023-03-14

当多个goroutine以取消信号为目标时,通常通过关闭一个通道来完成,而不是在通道上发送值。无论有多少Goroutine这样做,从封闭通道接收信息都可以立即进行。在通道上发送的值最多只能接收一次,因此不适合用一个值向多个goroutine发送信号。规格:接收操作员:

封闭通道上的接收操作始终可以立即进行,在接收到之前发送的任何值后,生成元素类型的零值。

现在,如果您关闭quit频道,这并不保证您的函数会立即返回。

首先,在不选中quit的情况下递归到左子级,该调用将执行相同的操作(直到到达nil左子级)。

其次,如果可以在ch上发送值,则两种情况都已准备就绪,因此select随机选择其中一种情况,这可能是quit情况,也可能不是。有关详细信息,请参见当涉及多个通道时,select如何工作?

如果你想避免这些,你应该在你的函数中添加一个非阻塞的退出检查作为第一件事:

func walkImpl(t *tree.Tree, ch, quit chan int) {
    select {
    case <-quit:
        return
    default: // This empty default makes it a non-blocking check
    }

    if t == nil {
        return
    }
    walkImpl(t.Left, ch, quit)
    select {
    case ch <- t.Value:
        // Value successfully sent.
    case <-quit:
        return
    }
    walkImpl(t.Right, ch, quit)
}

现在有人可能会问我们是否还需要第二个select中的quit案例,因为我们已经在walkinpl()中首先检查了它。答案是,您也应该保留该选项,因为如果在ch上发送将被阻止(例如,当quit关闭时,消费者将被关闭),则发送操作可能会永远被阻止。这样(当quit关闭时)可以保证函数返回。

 类似资料:
  • 本文向大家介绍Android Handler内存泄漏详解及其解决方案,包括了Android Handler内存泄漏详解及其解决方案的使用技巧和注意事项,需要的朋友参考一下 关联篇:深入Android的消息机制源码详解-Handler,MessageQueue与Looper关系 关联篇:HandlerThread 使用及其源码完全解析 在android开发过程中,我们可能会遇到过令人奔溃的OOM异

  • 本文向大家介绍IOS 常见内存泄漏以及解决方案,包括了IOS 常见内存泄漏以及解决方案的使用技巧和注意事项,需要的朋友参考一下 IOS 常见内存泄漏以及解决方案 整理了几个内存泄漏的例子,由于转载地址已经找不到了,在这里就不一一列出来了。 1 OC和CF转化出现的内存警告 2,循环参照 A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释放。 这种问题常发生于把del

  • 问题内容: 我有一个Python程序,它运行一系列实验,没有打算从一个测试存储到另一个测试的数据。我的代码包含一个我完全找不到的内存泄漏(我已经查看了内存泄漏的其他线程)。由于时间限制,我不得不放弃寻找泄漏的机会,但是如果我能够隔离每个实验,该程序可能会运行足够长的时间以产生所需的结果。 在单独的线程中运行每个测试是否有帮助? 还有其他隔离泄漏影响的方法吗? 具体情况详 我的代码分为两部分:实验运

  • 问题内容: 我正在尝试解决等效的二叉树演习。这是我所做的; 但是,我无法找出如何发信号通知树中是否还剩下任何元素。我无法使用on,因为它会使通道在所有值发送之前关闭(因为递归。)有人可以在这里帮我吗? 问题答案: 如果Walk函数本身不递归,则可以使用close()。即步行将做: 其中walkRecurse或多或少是您当前的Walk功能,但是在walkRecurse上递归。(或者您将Walk重写为

  • 在阅读了大量有关MAT的内容后,我使用我的生产堆转储来分析内存泄漏问题。下面是泄漏报告错误: 线程org.apache.tomcat.util.threads.taskthread@0x6d8be0a30 http-bio-8443-exec-115保留总大小为3,695,816,440(89.03%)字节的局部变量。 内存累积在“'<'System class Loader'>”加载的“java

  • 本文向大家介绍PHPExcel内存泄漏问题解决方法,包括了PHPExcel内存泄漏问题解决方法的使用技巧和注意事项,需要的朋友参考一下 使用 PHPExcel 来生成 excel 文档是比较消耗内存的,有时候可能会需要通过一个循环来把大数据切分成若干个小的 excel 文档保存来避免内存耗尽。 然而 PHPExcel 存在 circular references 的情况(貌似在最新的 1.6.5