1 回答
TA贡献1836条经验 获得超4个赞
你是对的,这WaitGroup可能就是你想要的。但是,您没有正确使用它。首先,您需要在wg.Add(1)调用wg.Done(). 其次,调用wg.Wait()块直到等待组中的所有 go routines 完成执行,所以你不希望它并发执行。
至于短路,确实没有什么好办法。我的建议是使用上下文。在这种情况下,您必须做的一件事是将上下文连接到您的调用中,nodeHasCycle如果您想要真正的短路行为。
修复你的代码,我们有:
func (c *cycleDet) hasCycle() bool {
ctx, cancel := context.WithCancel(context.Background())
hasCycle := make(chan bool)
var wg sync.WaitGroup
adj := c.b // adjacency list representation of the unerlying graph
for node := range adj {
wg.Add(1)
go func(ctx context.Context, no nodeID, co chan<- bool, cancel context.CancelFunc) {
// Use wg to synchronize termination of read-only goroutines.
defer wg.Done()
select {
case <-ctx.Done():
return
default:
}
visited := make(map[nodeID]struct{})
// c.nodeHasCycle will use a recursive implementation of DFS to
// find out if the node no leads to a cycle.
if c.nodeHasCycle(ctx, no, visited) {
co <- true
cancel()
return
}
}(ctx, node, hasCycle, cancel)
}
// Observer goroutine to notify when wg is done waiting.
time.Sleep(100 * time.Millisecond)
wg.Wait()
defer cancel()
select {
case <-hasCycle:
fmt.Println("got a cycle")
return true
default:
fmt.Println("no cycle detected")
return false
}
}
通过这种方式设置,您可以确保对 go-routine 的所有调用都将运行,除非找到一个循环,在这种情况下,不会调用其他 go-routes 并且,如果您添加逻辑以检查是否取消nodeHasSycle,则您也可以停止对任何正在运行的调用的执行。
- 1 回答
- 0 关注
- 100 浏览
添加回答
举报