duangan4406 2011-11-09 06:25
浏览 20
已采纳

我收到的以下go代码出了什么问题:“所有goroutine都处于睡眠状态-死锁!”

I'm trying to implement an Observer Pattern suggested here; Observer pattern in Go language

(the code listed above doesn't compile and is incomplete). Here, is a complete code that compiles but I get deadlock error.

package main

import (
    "fmt"
)

type Publisher struct{
    listeners []chan int
}

type Subscriber struct{
    Channel chan int
    Name string
}

func (p *Publisher) Sub(c chan int){
    p.listeners = append(p.listeners, c)
}

func (p *Publisher) Pub(m int, quit chan int){
    for _, c := range p.listeners{
        c <- m
    }
    quit <- 0
}

func (s *Subscriber) ListenOnChannel(){
    data := <-s.Channel
    fmt.Printf("Name: %v; Data: %v
", s.Name, data)            
}

func main() {
    quit := make(chan int)
    p := &Publisher{}
    subscribers := []*Subscriber{&Subscriber{Channel: make(chan int), Name: "1"}, &Subscriber{Channel: make(chan int), Name: "2"}, &Subscriber{Channel: make(chan int), Name: "3"}}
    for _, v := range subscribers{
        p.Sub(v.Channel)
        go v.ListenOnChannel() 
    }

    p.Pub(2, quit)

    <-quit              
}

Also, if I get rid of 'quit' completely, I get no error but it only prints first record.

  • 写回答

2条回答 默认 最新

  • donglang8008 2011-11-09 07:51
    关注

    The problem is that you're sending to quit on the same goroutine that's receiving from quit.

    quit has a buffer size of 0, which means that in order to proceed there has to be a sender on one side and a receiver on the other at the same time. You're sending, but no one's on the other end, so you wait forever. In this particular case the Go runtime is able to detect the problem and panic.

    The reason only the first value is printed when you remove quit is that your main goroutine is exiting before your remaining two are able to print.

    Do not just increase channel buffer sizes to get rid of problems like this. It can help (although in this case it doesn't), but it only covers up the problem and doesn't truly fix the underlying cause. Increasing a channel's buffer size is strictly an optimization. In fact, it's usually better to develop with no buffer because it makes concurrency problems more obvious.

    There are two ways to fix the problem:

    • Keep quit, but send 0 on it in each goroutine inside ListenOnChannel. In main, make sure you receive a value from each goroutine before moving on. (In this case, you'll wait for three values.)
    • Use a WaitGroup. There's a good example of how it works in the documentation.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 关于用python写支付宝扫码付异步通知收不到的问题
  • ¥50 vue组件中无法正确接收并处理axios请求
  • ¥15 隐藏系统界面pdf的打印、下载按钮
  • ¥15 MATLAB联合adams仿真卡死如何解决(代码模型无问题)
  • ¥15 基于pso参数优化的LightGBM分类模型
  • ¥15 安装Paddleocr时报错无法解决
  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改