使用goroutines时发生死锁



我有一个程序可以做两件事:

  • 读取日志条目并创建logEntry对象
  • 处理每个logEntry实例

这里,读取由单独的goroutine完成,所有读取条目的处理由单个goroutine执行。

我使用一个等待组-wg来确保在程序退出之前读取所有日志条目,并使用一个信号通道-done来确保日志条目的处理完成。

waitgroup按预期工作,但是当我调用<-done以确保程序仅在读取的日志文件被处理后退出时,它会抛出错误fatal error: all goroutines are asleep - deadlock!

有人能解释一下为什么会发生这种情况,以及如何修复上述错误吗?

main.go:

package main
import (
"fmt"
"sync"
"time"
)
type logEntry struct {
lines      []string
created_at string
line_count int
}
var wg sync.WaitGroup
func main() {
linesChan := make(chan (logEntry))
done := make(chan (bool), 1)
// Process entries from lines
go func() {
for c := range linesChan {
time.Sleep(100 * time.Millisecond)
fmt.Printf("%vn", c)
}
done <- true
}()
// Read lines
for i := 1; i <= 10; i++ {
wg.Add(1)
go func(i int, linesChan chan (logEntry)) {
read(i, linesChan)
}(i, linesChan)
}
// Wait till all the files are read
wg.Wait()
// Wait till all the log entries are processed
<-done
close(done)
}
func read(count int, channel chan (logEntry)) {
fmt.Println(count, "read")
channel <- logEntry{
line_count: count,
}
wg.Done()
}

输出:

10 read
6 read
3 read
1 read
4 read
8 read
7 read
2 read
5 read
9 read
{[]  10}
{[]  6}
{[]  3}
{[]  1}
{[]  4}
{[]  8}
{[]  7}
{[]  2}
{[]  5}
{[]  9}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
.../main.go:44 +0x13a
goroutine 18 [chan receive]:
main.main.func1()
.../main.go:24 +0x145
created by main.main
.../main.go:23 +0x9d
exit status 2

在您的情况下,您正在侦听linesChan,但没有关闭它。您需要关闭此通道,届时所有数据都将被传递。done <- true不会被执行。

但这里不需要同步通道,sync.WaitGroup{}就足够了。

package main
import (
"fmt"
"sync"
"time"
)
type logEntry struct {
lines      []string
created_at string
line_count int
}
var wg sync.WaitGroup
func main() {
linesChan := make(chan (logEntry))
// Process entries from lines
go func() {
for c := range linesChan {
time.Sleep(100 * time.Millisecond)
fmt.Printf("%vn", c)
}
}()
// Read lines
for i := 1; i <= 10; i++ {
wg.Add(1)
go func(i int, linesChan chan (logEntry)) {
read(i, linesChan)
}(i, linesChan)
}
// Wait till all the files are read
wg.Wait()
}
func read(count int, channel chan (logEntry)) {
fmt.Println(count, "read")
channel <- logEntry{
line_count: count,
}
wg.Done()
}

最新更新