我正在尝试Go进行一些文件系统使用分析,我尽可能快地生成代码,将几乎所有内容都作为goroutine生成并依赖Go VM(和GOMAXPROCS)来管理它。我正在看这个代码运行(非常快)直到它刚刚停止。我检查了顶部,它将我的进程列为1500个线程。
我想也许我已经遇到了一些限制,因此这个过程在操作系统上等待死锁。我检查了我的操作系统(FreeBSD)限制,确定每个进程最多列出1500个线程。
很惊讶,我检查了Go文档,它说GOMAXPROCS只是运行线程的限制,但是阻塞的线程不计算在内。
所以我的问题:
公平地说,我不能依赖Go VM作为全局池,以防止达到这些类型的操作系统限制吗?
有没有一种惯用的方式来处理这个问题(很好,这只是我第二天使用Go)?
特别是,当我使用它时,我没有找到除关闭频道以外的好方法。有更好的方法吗?
我想抽象掉样板(用例程和并行映射) 完成时关闭通道),有没有类型安全的方法来做这个没有泛型?
这是我目前的代码:
func AnalyzePaths(paths chan string) chan AnalyzedPath {
analyzed := make(chan AnalyzedPath)
go func() {
group := sync.WaitGroup{}
for path := range paths {
group.Add(1)
go func(path string) {
defer group.Done()
analyzed <- Analyze(path)
}(path)
}
group.Wait()
close(analyzed)
}()
return analyzed
}
func GetPaths(roots []string) chan string {
globbed := make(chan string)
go func() {
group := sync.WaitGroup{}
for _, root := range roots {
group.Add(1)
go func(root string) {
defer group.Done()
for _, path := range glob(root) {
globbed <- path
}
}(root)
}
group.Wait()
close(globbed)
}()
return globbed
}
func main() {
paths := GetPaths(patterns)
for analyzed := range AnalyzePaths(paths) {
fmt.Println(analyzed)
}
}
答案 0 :(得分:3)
大约2个月前(或更多)语言开发人员谈到了线程计数控制(以及其他一些限制)的入侵。所以我们很快就能看到它。一个月或更久以前我开发问题,并在我的linux机器上发现GOMAXPROCS不超过256的值。如果我发送300或更多,结果总是256.但我发现goroutines不是一个线程。 Goroutines可以生活在一个线程中。
至于惯用同步 - 我认为没有必要同步太多。 在我的代码中,我通常使用goroutines仅通过通道进行通信的想法。并且通道应作为goroutines的参数传递。
func main() {
ch1 := make(chan SomeType1)
ch2 := make(chan SomeType2)
go generator(ch1, ch2)
go processor(ch1, ch2)
// here main func becomes waiting until it capture 2 of ch2-finished-signals
<- ch2
<- ch2
// usually we don't need the exact values of ch2-signals,
// so we assign it to nothing
}
func generator(ch1 chan SomeType1, ch2 chan SomeType2) {
for (YOUR_CONDITION){
// generate something
//....
// send to channel
ch1 <- someValueOfType1
}
ch1 <- magicStopValue
ch2 <- weAreFinishedSignal1
}
func processor(ch1 chan SomeType1, ch2 chan SomeType2) {
// "read" value from ch1
value := <-ch1
for value != magicStopValue {
// make some processing
// ....
//get next value from ch1 and replay processing
value = <- ch1
}
// here we can send signal that goroutine2 is finished
ch2 <- weAreFinishedSignal2
}
如果goroutines在一个线程中,则它们的通信速度更快。至于我,频道表现远非好,但足以达到很多目的。