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条)

报告相同问题?

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集