首页 > 解决方案 > Go中的多线程无限循环

问题描述

为了帮助扩展我的围棋知识,我决定为Collat​​z 猜想编写一个迭代器。让它工作后,我现在想让它成为多线程的。我可以找到多线程 for 循环的各种示例,但它们似乎是基于定义边界之间的每次迭代的线程。例如for n := range(10) {。在我的用例中,N 的上限是未知的(取决于代码运行多长时间)。完整的代码可以在 Github上看到,但总结一下:

n := 0
for {
    stepsToResolve = resolveN(n) //<- "Multithread this"
    n++
}

标签: go

解决方案


您的示例缺少退出条件,因此有点奇怪。话虽如此,您并不总是事先知道您将要启动多少子程序。处理此问题的典型方法是使用sync.WaitGroup. 例如:

for {
        wg.Add(1) // declare new goroutine
        go func(i int, wg *sync.WaitGroup) {
            defer wg.Done() // when work is done, declare termination
            log.Printf("hello wait group %v\n", i)
        }(i, &wg)
        // Please add a stop condition !
    }

wg.Wait() // prevent your main program to return until all goroutines have ended

但是在您的情况下,创建数千个 goroutine 似乎无济于事(您的可用 CPU 可能较少)。在这种情况下,您可以改用具有有限并发性的池。如果您愿意使用它,我为此编写了一个库

import "github.com/aherve/gopool"

func main() {
    pool := gopool.NewPool(8) // creates pool with limited concurrency of 8
    for {
        pool.Add(1)
        go func(i int, pool *gopool.GoPool) {
            defer pool.Done()
            time.Sleep(time.Second)
            log.Printf("hello pool %v\n", i)
        }(i, pool)
        // Please add a stop condition !
    }
    pool.Wait()
}

在这个版本中,不会超过 8 个例程同时启动,并且代码仍然与waitGroup用法非常相似。


推荐阅读