首页 > 后端开发 > Golang > 正文

当生产者寿命较短时,如何避免 Go Goroutine 死锁?

Linda Hamilton
发布: 2024-10-25 07:09:02
原创
792 人浏览过

How to Avoid Deadlock in Go Goroutines When Producers Are Short-Lived?

解决 Go Goroutine 中的死锁

在并发编程中,当多个 Goroutine 无限期地等待彼此完成操作时,就会发生死锁,从而有效地停止进程程序。本文解决了 Go 并发中遇到的特定死锁,如原始问题中所述:

<code class="go">package main

import (
    "fmt"
    "time"
)

func producer(ch chan int, d time.Duration, num int) {
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    ch := make(chan int)
    go producer(ch, 100*time.Millisecond, 2)
    go producer(ch, 200*time.Millisecond, 5)
    for {
        fmt.Println(<-ch)
    }
    close(ch)
}</code>
登录后复制

此代码由于以下因素触发死锁错误:

  • 生产者向通道发送值的过程是短暂的,最终会停止产生数据。
  • 主函数中的无限 for 循环不断从通道接收值,没有终止条件。
  • 无限循环后通道关闭,导致没有更多的值可用于接收。

解决方案:协调终止

为了避免死锁,生产者必须协调以发出完成信号,并且通道必须由最后一个生产者关闭。这是使用sync.WaitGroup进行协调的有效解决方案:

<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan int)

    wg.Add(1)
    go producer(ch, 100*time.Millisecond, 2, wg)
    wg.Add(1)
    go producer(ch, 200*time.Millisecond, 5, wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
}</code>
登录后复制

在此解决方案中:

  • 我们为每个生产者增加WaitGroup。
  • 每个生产者通过 defer 语句在完成后递减 WaitGroup。
  • goroutine 等待 WaitGroup 达到零(意味着所有生产者都完成)并关闭通道。
  • 主循环使用 for range构造以在关闭之前迭代通道上发送的值。

以上是当生产者寿命较短时,如何避免 Go Goroutine 死锁?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!