在取消通道上传递任何值会导致程序挂起

时间:2016-04-11 13:34:24

标签: go

我正在尝试使用工作器goroutines检查直径到一定距离,当我一次做一个瓦片时效果很好,但是当我做一堆时,会出现大幅减速。我认为这是因为即使不再需要它们,许多goroutine仍在运行。我添加了一个故障通道来告诉所有正在运行的goroutine关闭商店,但这样做会导致应用程序挂起。实际上,将任何值传递给频道都会导致应用挂起,即使我没有消费它。

 caught := 0
loop:
    for angle := float64(0); angle < 360; angle++ {
        select {
        case <-failChannel:
            break loop
        default:
         log.Print(angle)
        }

    }
    channelOut <- []int{radius, caught}

是使用频道的例程

for {
        select {
        case circle := <-channelOut:
            if circle[1] == 0 {
                radiusMap[circle[0]] = 0
                if _, radius := testLine(radiusMap); radius <= circle[0] {
                    failChannel <- 0


                }
            } else {
                radiusMap[circle[0]] = 1

            }

        default:    
        }
    }

是将int传递给failChannel的循环。我正在做一个int通道,因为我想看看下半径是否失败,如果是这样,就停止。我现在只做任何一个int作为测试。

有没有人知道为什么会挂?它似乎对我没有意义。

1 个答案:

答案 0 :(得分:2)

您可以关闭频道以表示完成:

failed := make(chan struct{})
select {
case <-failed:
}

在另一个goroutine中:

close(failed)

会导致failed案件发生。这适用于在failed上收听的任意数量的goroutine。但是要小心,只做一次,因为关闭一个已经很近的通道会引起恐慌。你可以使用这种模式:

// A Stopper signals completion over C by closing it when Stop is called
type Stopper struct {
    C    chan struct{}
    once sync.Once
}

// NewStopper creates a new Stopper
func NewStopper() *Stopper {
    return &Stopper{
        C: make(chan struct{}),
    }
}

// Stop closes C. It is safe to call multiple times
func (s *Stopper) Stop() {
    s.once.Do(func() {
        close(s.C)
    })
}
相关问题