如何在不产生死锁的情况下拥有一个缓冲通道和多个阅读器?

Posted

技术标签:

【中文标题】如何在不产生死锁的情况下拥有一个缓冲通道和多个阅读器?【英文标题】:How can I have one buffered channel and multiple readers without producing a deadlock? 【发布时间】:2016-06-06 17:41:54 【问题描述】:

致命错误 所有 goroutine 都处于休眠状态。死锁。

这是我尝试过的。我打电话给wg.Done()。缺少什么?

package main

import (
    "fmt"
    "strconv"
    "sync"
)

func sender(wg *sync.WaitGroup, cs chan int) 
    defer wg.Done()
    for i := 0; i < 2; i++ 
        fmt.Println(i)
        cs <- i
    


func reciever(wg *sync.WaitGroup, cs chan int) 
    x, ok := <-cs
    for ok 
        fmt.Println("Retrieved" + strconv.Itoa(x))
        x, ok = <-cs
        if !ok 
            wg.Done()
            break
        
    


func main() 
    wg := &sync.WaitGroup
    cs := make(chan int, 1000)
    wg.Add(1)
    go sender(wg, cs)
    for i := 1; i < 30; i++ 
        wg.Add(1)
        go reciever(wg, cs)
    
    wg.Wait()
    close(cs)

【问题讨论】:

【参考方案1】:

你应该在wg.Wait之前关闭频道。 您所有的接收器都在等待来自通道的数据。这就是你有死锁的原因。 您可以在sender函数的defer语句处关闭频道。 如果第一次尝试从频道接收不成功(因为频道已经关闭),您还需要wg.Done()

http://play.golang.org/p/qdEIEfY-kl

【讨论】:

【参考方案2】:

有几件事:

    发送者完成后,您需要关闭通道。 在接收器中,覆盖通道 不需要在等待组中添加1并在sender中调用Done

请参考http://play.golang.org/p/vz39RY6WA7

【讨论】:

以上是关于如何在不产生死锁的情况下拥有一个缓冲通道和多个阅读器?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取无缓冲通道中的元素数量

如何在没有超时/死锁的情况下在PROMELA进程中发送和接收?

dequeueBuffer: 不能在不设置缓冲区计数的情况下使多个缓冲区出队

线程死锁

如何在不复制列标签的情况下将多个数据框写入同一张表

Java -- 每日一问:什么情况下Java程序会产生死锁?如何定位修复?