停止 goroutine 中的所有递归函数
Stop all recursive functions in a goroutine
启动一个 运行 递归函数的 goroutine,我想发送一个信号来停止那些递归函数。这是功能(功能不重要):
func RecursiveFunc(x int, depth int, quit chan bool) int {
if depth == 0 {
return 1
}
if quit != nil {
select {
case <-quit:
return 0
default:
}
}
total := 0
for i := 0; i < x; i++ {
y := RecursiveFunc(x, depth - 1, quit)
if y > 0 {
total += y
}
}
return total
}
这个函数可能需要很长时间才能完成,我想在发送退出信号后停止它并使用结果(无论它是什么)。给运行吧:
import (
"fmt"
"time"
"sync"
)
func main() {
quit := make(chan bool)
wg := &sync.WaitGroup{}
result := -1
go func() {
defer wg.Done()
wg.Add(1)
result = RecursiveFunc(5, 20, quit)
}()
time.Sleep(10 * time.Millisecond)
close(quit) // Using `quit <- true` doesn't work
wg.Wait()
fmt.Println(result)
}
为了停止 goroutine,我使用了一个通道 quit
并在关闭它后,程序运行良好,但是我不想真正关闭通道,我只想发送一个信号 quit <- true
。但是,quit <- true
不起作用,我可能只退出了一个递归实例。
如何通过发送退出信号停止递归函数的所有实例?
尝试添加标志以继续执行,但它可能不是线程安全的。
var finishIt bool
func RecursiveFunc(x int, depth int, quit chan bool) int {
if finishIt {
return 0
}
//other code here
}
//some code here, but than we decide to stop it
finishIt = true
您可以使用 context.
完成您要执行的操作
你可以将一个context.Context
对象作为第一个参数传递给你需要从外部停止的函数,然后调用相应的cancel
函数发送一个"cancellation signal"到函数,这将导致 context.Context
的 Done()
通道关闭,因此被调用函数将在 select
语句中被通知取消信号。
以下是函数如何使用 context.Context
处理取消信号:
func RecursiveFunc(ctx context.Context, x int, depth int) int {
if depth == 0 {
return 1
}
select {
case <-ctx.Done():
return 0
default:
}
total := 0
for i := 0; i < x; i++ {
y := RecursiveFunc(ctx, x, depth-1)
if y > 0 {
total += y
}
}
return total
}
下面是如何使用新签名调用函数:
func main() {
wg := &sync.WaitGroup{}
result := -1
ctx, cancel := context.WithCancel(context.Background())
go func() {
defer wg.Done()
wg.Add(1)
result = RecursiveFunc(ctx, 5, 20)
}()
time.Sleep(10 * time.Millisecond)
cancel()
wg.Wait()
fmt.Println(result)
}
我最近遇到了类似的情况,就像你的情况一样,退出信号被一个递归分支消耗掉了,而其他分支没有信号。我通过在从函数返回之前将停止信号转发到通道来解决这个问题。
比如可以将递归函数里面的select修改为:
if quit != nil {
select {
case <-quit:
quit <- true // forward the signal
return 0
default:
}
}
启动一个 运行 递归函数的 goroutine,我想发送一个信号来停止那些递归函数。这是功能(功能不重要):
func RecursiveFunc(x int, depth int, quit chan bool) int {
if depth == 0 {
return 1
}
if quit != nil {
select {
case <-quit:
return 0
default:
}
}
total := 0
for i := 0; i < x; i++ {
y := RecursiveFunc(x, depth - 1, quit)
if y > 0 {
total += y
}
}
return total
}
这个函数可能需要很长时间才能完成,我想在发送退出信号后停止它并使用结果(无论它是什么)。给运行吧:
import (
"fmt"
"time"
"sync"
)
func main() {
quit := make(chan bool)
wg := &sync.WaitGroup{}
result := -1
go func() {
defer wg.Done()
wg.Add(1)
result = RecursiveFunc(5, 20, quit)
}()
time.Sleep(10 * time.Millisecond)
close(quit) // Using `quit <- true` doesn't work
wg.Wait()
fmt.Println(result)
}
为了停止 goroutine,我使用了一个通道 quit
并在关闭它后,程序运行良好,但是我不想真正关闭通道,我只想发送一个信号 quit <- true
。但是,quit <- true
不起作用,我可能只退出了一个递归实例。
如何通过发送退出信号停止递归函数的所有实例?
尝试添加标志以继续执行,但它可能不是线程安全的。
var finishIt bool
func RecursiveFunc(x int, depth int, quit chan bool) int {
if finishIt {
return 0
}
//other code here
}
//some code here, but than we decide to stop it
finishIt = true
您可以使用 context.
完成您要执行的操作你可以将一个context.Context
对象作为第一个参数传递给你需要从外部停止的函数,然后调用相应的cancel
函数发送一个"cancellation signal"到函数,这将导致 context.Context
的 Done()
通道关闭,因此被调用函数将在 select
语句中被通知取消信号。
以下是函数如何使用 context.Context
处理取消信号:
func RecursiveFunc(ctx context.Context, x int, depth int) int {
if depth == 0 {
return 1
}
select {
case <-ctx.Done():
return 0
default:
}
total := 0
for i := 0; i < x; i++ {
y := RecursiveFunc(ctx, x, depth-1)
if y > 0 {
total += y
}
}
return total
}
下面是如何使用新签名调用函数:
func main() {
wg := &sync.WaitGroup{}
result := -1
ctx, cancel := context.WithCancel(context.Background())
go func() {
defer wg.Done()
wg.Add(1)
result = RecursiveFunc(ctx, 5, 20)
}()
time.Sleep(10 * time.Millisecond)
cancel()
wg.Wait()
fmt.Println(result)
}
我最近遇到了类似的情况,就像你的情况一样,退出信号被一个递归分支消耗掉了,而其他分支没有信号。我通过在从函数返回之前将停止信号转发到通道来解决这个问题。
比如可以将递归函数里面的select修改为:
if quit != nil {
select {
case <-quit:
quit <- true // forward the signal
return 0
default:
}
}