Multi-thread infinite loop in Go

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

Multi-thread infinite loop in Go

问题

为了扩展我的Go知识,我决定为Collatz猜想编写一个迭代器。在使其正常工作后,我现在想将其改为多线程。我可以找到一些多线程for循环的示例,但它们似乎是基于在定义的范围内每次迭代创建一个线程。例如,for n := range(10) {。在我的用例中,N的上限是未知的(取决于代码运行的时间)。完整的代码可以在Github上看到,但简要概括如下:

n := 0
for {
    stepsToResolve = resolveN(n) //<- "将此部分改为多线程"
    n++
}
英文:

To help expand my Go knowledge, I decided to write an iterator for the Collatz Conjecture. Having got it working, I'd now like to make it multi-threaded. I can find various examples of multi-threading a for loop but they appear to be based on a thread per iteration between defined bounds. E.g. for n := range(10) {. In my use case, the upper bound of N is unknown (depending on how long the code is left running). The full code can be seen on Github but, in summary:

n := 0
for {
    stepsToResolve = resolveN(n) //&lt;- &quot;Multithread this&quot;
    n++
}

答案1

得分: 2

你的示例缺少退出条件,所以有点奇怪。话虽如此,你并不总是事先知道要启动多少个子例程。处理这种情况的一种典型方法是使用sync.WaitGroup。例如:

for {
        wg.Add(1) // 声明新的goroutine
		go func(i int, wg *sync.WaitGroup) {
			defer wg.Done() // 工作完成后,声明终止
			log.Printf("hello wait group %v\n", i)
		}(i, &wg)
        // 请添加停止条件!
	}

wg.Wait() // 防止主程序在所有goroutine结束之前返回

但在你的情况下,创建成千上万个goroutine可能没有帮助(可能可用的CPU较少)。在这种情况下,你可以使用具有有限并发性的池。如果你想使用它,我写了一个

import "github.com/aherve/gopool"

func main() {
	pool := gopool.NewPool(8) // 创建具有有限并发性为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)
        // 请添加停止条件!
	}
	pool.Wait()
}

使用这个版本,最多同时启动8个例程,并且代码与使用waitGroup的方式非常相似。

英文:

Your example lacks an exit condition so it's a bit weird. That being said, you don't always know in advance how many subroutines you are about to launch. A typical way of dealing with this is to use sync.WaitGroup. For instance:

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(&quot;hello wait group %v\n&quot;, i)
		}(i, &amp;wg)
        // Please add a stop condition !
	}

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

But in your case it looks like creating thousands of goroutines won't help (you probably have less CPUs available). In that case you can use a pool with limited concurrency instead. If you care to use it, I wrote a library for that:

import &quot;github.com/aherve/gopool&quot;

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(&quot;hello pool %v\n&quot;, i)
		}(i, pool)
        // Please add a stop condition !
	}
	pool.Wait()
}

With this version, no more than 8 routines will be launched simultaneously, and the code remains pretty similar to a waitGroup usage.

huangapple
  • 本文由 发表于 2021年8月8日 20:41:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/68700893.html
匿名

发表评论

匿名网友

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

确定