Goroutines死锁递归

huangapple go评论84阅读模式
英文:

Goroutines deadlock recursive

问题

我有一个深度优先搜索(DFS)递归函数,它可以给我在有向图中的所有可能路径。
但是我无法准确知道它何时完成。

func dfs(data map[int][]int, path []int) {
	datum := path[len(path)-1]
	value := data[datum]
	for i := 0; i < len(value); i++ {
		if !contains(path, value[i]) {
			new_path := append(path, []int{value[i]}...)
			if len(new_path) > len(max_path) {
				max_path = new_path
			}
			dfs(data, new_path)
		}
	}
}

我尝试在不同情况下使用goroutines来执行这个函数,以减少时间。通过使用goroutines,我可以大大提高速度(大约是10倍)。

for _, node := range nodes {
	if is_touching_wall(node) {
		wg.Add(1)
		go dfs(graph, []int{node})
	}
}

wg.Wait()

正如你所理解的,我调用了wg.Add(1),但是没有调用wg.Done()。这会导致"fatal error: all goroutines are asleep - deadlock!"的错误。

我试图找到DFS完成的时间,以便调用Done(),但是无法成功。

是否有其他方法可以在goroutines即将发生死锁时取消它们,或者我应该尝试另一种方法?

英文:

I have a DFS recursive function which gives me all possible routes in a directed graph.
And I can't precisely know when it finishes.

func dfs(data map[int][]int, path []int) {
	datum := path[len(path)-1]
	value := data[datum]
	for i := 0; i &lt; len(value); i++ {
		if !contains(path, value[i]) {
			new_path := append(path, []int{value[i]}...)
			if len(new_path) &gt; len(max_path) {
				max_path = new_path
			}
			dfs(data, new_path)
		}
	}
}

I try to execute this function on goroutines for different cases. In order to reduce time I use goroutines. (By the way it really speeds things up like 10x or much)

for _, node := range nodes {
		if is_touching_wall(node) {
			wg.Add(1)
			go dfs(graph, []int{node})
		}
	}

	wg.Wait()

As you can understand here, I call wg.add(1) but i don't call wg.Done() later. So it creates "fatal error: all goroutines are asleep - deadlock!".

I tried to find the time when DFS finishes, in order to call Done() but couldn't manage it.

Is there any other way to cancel goroutines if they are going to be deadlocked or should i try another approach here ?

答案1

得分: 1

你使用goroutines的方式来进行这种方法,可能不会获得太多的收益。如果DFS在一棵树上运行,那么你可以将其分割成不相交的部分,并在每个部分上使用goroutines。但是对于有向图,你无法确定一个goroutine遍历的节点是否也被其他goroutine遍历。

然而,为了解决死锁问题,你必须在goroutine结束时调用wg.Done。一种简单的方法是:

wg.Add(1)
go func() {
   defer wg.Done()
   dfs(graph, []int{node})
}()

这只能解决死锁问题,而不能解决你的实际问题。

英文:

It is unlikely that you will gain much, if any, using goroutines the way you do for this approach. If the DFS is running on a tree, then you can potentially split it into disjoint sections and use goroutines on each. With a directed graph, you have no idea if nodes traversed by one goroutine are also being traversed by others.

Nevertheless, in order to deal with the deadlock, you must call wg.Done when a goroutine ends. A simple way of doing it is:

wg.Add(1)
go func() {
   defer wg.Done()
   dfs(graph, []int{node})
}()

This will not solve your real problem though, only the deadlocks.

huangapple
  • 本文由 发表于 2022年8月5日 06:55:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/73243007.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定