例如我有这段代码:
func main() {
go myRoutine(1, channel)
go myRoutine(2, channel)
go myRoutine(3, channel)
go myRoutine(4, channel)
for i := 0; i < 4; i++ {
fmt.Println("Returned routine:", <-channel)
}
}
func myRoutine(chnum int, c chan int) {
//doing some stuff here
c <- chnum
//and doing some stuff here
}
我希望myRoutine在写入频道后立即退出。 谷歌告诉我,如果我要退出我的goroutine,我应该有关机频道和信号。 我想知道在с&lt; - chnum?
之后添加回报是不够的关于goroutines的第二个问题: 当我启动我的应用程序时,它创建了4个进程(每个CPU核心一个),我的例程再添加两个。我是否应该在完成goroutines之后做一些事情来杀死这两个过程,或者Go自己做了什么?
答案 0 :(得分:1)
在“с&lt; - chnum”之后添加“return”语句是不够的。那是因为通道将阻塞,直到信息可以插入通道。此外,您需要考虑可能需要缓冲通道,以便可以从线程中插入和检索多个条目。考虑下面的代码,它使用缓冲的通道:
package main
import "fmt"
func main() {
numGoRountines := 10
c := make(chan int, numGoRountines)
for i := 0; i < numGoRountines; i++ {
go myRoutine(i, c)
}
for i := 0; i < numGoRountines; i++ {
fmt.Println("Returned routine:", <-c)
}
}
func myRoutine(chnum int, c chan int) {
//doing some stuff here
c <- chnum
//and doing some stuff here
}
可能的输出:
Returned routine: 9
Returned routine: 0
Returned routine: 1
Returned routine: 2
Returned routine: 3
Returned routine: 4
Returned routine: 5
Returned routine: 6
Returned routine: 7
Returned routine: 8
关于你的第二个问题,go会为你清理那些额外的goroutine。但请注意,如果父级死亡,子线程也会死亡。您可以在下面看到一个示例:
package main
import (
"fmt"
"sync"
)
func main() {
var waitGroupOnlyForParents sync.WaitGroup
numGoRountines := 4
for i := 0; i < numGoRountines; i++ {
waitGroupOnlyForParents.Add(1)
go myRoutine(&waitGroupOnlyForParents, i)
}
// makes main function waits for every one who calls the method Done() in our wait group
waitGroupOnlyForParents.Wait()
}
func myRoutine(wg *sync.WaitGroup, myId int) {
defer wg.Done()
numGoRountines := 2
for i := 0; i < numGoRountines; i++ {
go anotherRoutine(myId, i)
}
}
func anotherRoutine( parentId, childId int){
fmt.Printf("Created by %d, my name is %d\n", parentId, childId)
}
可能的输出:
Created by 3, my name is 1
Created by 0, my name is 1
Created by 1, my name is 1
现在假设我们希望同步所有线程,以确保每个线程都能完成所需的一切,我们会稍微更改代码:
package main
import (
"fmt"
"sync"
)
func main() {
var waitGroupForAllThreads sync.WaitGroup
numGoRountines := 4
for i := 0; i < numGoRountines; i++ {
waitGroupForAllThreads.Add(1)
go myRoutine(&waitGroupForAllThreads, i)
}
// makes main function waits for every one who calls the method Done() in our wait group
waitGroupForAllThreads.Wait()
}
func myRoutine(wg *sync.WaitGroup, myId int) {
defer wg.Done()
numGoRountines := 2
for i := 0; i < numGoRountines; i++ {
wg.Add(1)
go anotherRoutine(wg, myId, i)
}
}
func anotherRoutine(wg *sync.WaitGroup, parentId, childId int){
defer wg.Done()
fmt.Printf("Created by %d, my name is %d\n", parentId, childId)
}
可能的输出(在这种情况下,肯定会显示所有打印件,订单可能会更改):
Created by 3, my name is 1
Created by 0, my name is 1
Created by 1, my name is 1
Created by 2, my name is 1
Created by 3, my name is 0
Created by 0, my name is 0
Created by 1, my name is 0
Created by 2, my name is 0
答案 1 :(得分:1)
我想知道在с&lt; - chnum?
之后添加回报是不够的
确实如此。在goroutine中调用return
将定义它
只是不要忘记close
您的频道。
关于goroutines的第二个问题:当我启动我的应用程序时,它会创建4个进程(每个cpu核心一个),我的例程再添加两个进程。在完成goroutines之后我应该做些什么来杀死这两个过程,或者Go自己做了什么?
Goroutines不会产生额外的进程,它们是Go运行时内部的东西。当Go应用程序完成它的工作时,您的操作系统应该正确清理所有内容。