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

报告相同问题?

悬赏问题

  • ¥50 决策面并仿真,要求有仿真结果图
  • ¥15 springboot接入微信支付SDK
  • ¥50 大区域的遥感影像匹配 怎么做啊
  • ¥15 求解答:pytorch跑yolov8神经网络受挫
  • ¥20 Js代码报错问题不知道怎么解决
  • ¥15 gojs 点击按钮node的position位置进行改变,再次点击回到原来的位置
  • ¥20 halcon 图像拼接
  • ¥15 webstorm上开发的vue3+vite5+typeScript打包时报错
  • ¥15 vue使用gojs,需求在link中的虚线上添加方向箭头
  • ¥15 CSS通配符清除内外边距为什么可以覆盖默认样式?