返回顶部
首页 > 资讯 > 后端开发 > GO >无论我关闭通道与否,地图缩小都不起效果
  • 338
分享到

无论我关闭通道与否,地图缩小都不起效果

2024-04-04 23:04:12 338人浏览 八月长安
摘要

大家好,今天本人给大家带来文章《无论我关闭通道与否,地图缩小都不起效果》,文中内容主要涉及到,如果你对golang方面的知识点感兴趣,那就请各位朋友继续看下去吧~希望能真正帮到你们,谢谢!问题内容这

大家好,今天本人给大家带来文章《无论我关闭通道与否,地图缩小都不起效果》,文中内容主要涉及到,如果你对golang方面的知识点感兴趣,那就请各位朋友继续看下去吧~希望能真正帮到你们,谢谢!

问题内容

这是家庭作业和初学者问题。因为我发现了一个错误,所以我编辑了这个问题。

我正在尝试从文本中进行并行频率映射,但在最后一个操作(减少映射)中出现错误

到目前为止,代码似乎可以正常工作。

如果我关闭频道,则会收到错误消息: “恐慌:在封闭通道上发送”

如果我不关闭频道,我会得到: “致命错误:所有 Goroutine 都在睡觉 - 死!”

func WordCount(text string) {

    text = strings.ToLower(text)
    re := regexp.MustCompile("\\w+")
    sentence := re.FindAllString(text, -1)

    numberOfGroups := 4
    piece := len(sentence) / numberOfGroups

    wordChannel := make(chan map[string]int)

    wg := new(sync.WaitGroup)
    wg.Add(numberOfGroups)

    for i := 0; i < numberOfGroups; i ++ {
        go processToCounting(sentence[i*piece:(i+1)*piece], wordChannel, wg)
    }

    wg.Wait()
    fmt.Print(<-wordChannel)
    fmt.Print("\n")

    finalMap := make(map[string]int)
    close(wordChannel)

    for i := 0; i < numberOfGroups; i++ {
        for k, v := range <- wordChannel {
            finalMap[k] += v
        }
    }
}

func processToCounting(textSlice []string, wordChannel chan map[string]int, wg *sync.WaitGroup) {
    freq := make(map[string]int)
    for _, v := range textSlice {
        freq[v]++
    }
    wg.Done()
    wordChannel <- freq
}


解决方案


<强>1。第一个问题:恐慌

如果我关闭通道,我会收到错误:“恐慌:在关闭的通道上发送”

为什么?其中一个 goroutine 正在尝试写入您已在调用(主)goroutine 中关闭的通道。在您的情况下,在 wordcount 函数中。

在当前版本的代码中,panic is not reproducible 带有我的测试语句,但您很容易导致此问题,例如如果您要在 wg.wait() 之前调用 close(wordchannel)

让我们看看 processtocounting 中可能导致 panicbug

wg.done() // tells to the waitgroup that the gouroutine is done (decrements the counter of goroutines)
wordchannel <- freq // trying to write to the channel

这里 wg.done() 在实际写入通道之前向 waitgroup 发出信号,告知 goroutine 是 done。调用 goroutine(wordcount 函数)在某个时刻认为所有 goroutine 都已完成(wg.wait() 行)并关闭通道。但是你的一个尚未完成写入的 goroutine 会尝试写入已关闭的通道。然后你会得到panic

如何修复:

processtocounting 函数中使用 defer

defer wg.done() // triggers wg.done right before the function returns (but after writing to the channel in your case)

阅读内容:

初学者请参阅A Tour of Go / Concurrency

在封闭的通道上发送会导致恐慌。

和文档:close

发送或关闭已关闭的通道会导致运行时恐慌。

<强>2。第二个问题:死锁

如果我不关闭通道,我会得到:“致命错误:所有 goroutine 都在睡觉 - 死锁!”

您有一个从通道读取数据的 for 循环。这个for循环被永远锁定。等待来自通道的新值,但没有人会再在那里写入。

参见 A Tour of Go / Concurrency

循环 for i := range c 重复从通道接收值,直到关闭。

并查看 Channels 的文档

接收器总是阻塞,直到有数据要接收

问题1:为什么close(wordchannel)会触发panic

答:

  1. 在将结果推送到通道之前放置 wg.done()
  2. 该通道是非缓冲通道,这意味着它将被卡住以进行写入,直到有读取为止。但读取会在您关闭通道后发生。顺序是关闭通道 -> 读取通道 -> 写入通道 -> 恐慌

问题2:为什么会出现死锁。

a: fmt.print(<-wordchannel) 从通道读取一条消息,导致最后一个循环无法读取 numberofgroups 消息。它永远等待最后一条消息。

for i := 0; i < numberOfGroups; i++ {
        for k, v := range <- wordChannel {
            finalMap[k] += v
        }
    }

今天关于《无论我关闭通道与否,地图缩小都不起效果》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注编程网公众号!

您可能感兴趣的文档:

--结束END--

本文标题: 无论我关闭通道与否,地图缩小都不起效果

本文链接: https://lsjlt.com/news/595769.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 无论我关闭通道与否,地图缩小都不起效果
    大家好,今天本人给大家带来文章《无论我关闭通道与否,地图缩小都不起效果》,文中内容主要涉及到,如果你对Golang方面的知识点感兴趣,那就请各位朋友继续看下去吧~希望能真正帮到你们,谢谢!问题内容这...
    99+
    2024-04-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作