执行:读取文件,goroutine死锁

时间:2019-04-17 03:03:42

标签: go

我有两组代码-读取具有随机文本行的文件,并将每一行加载到一个通道。我不明白为什么会返回错误。但是另一个没有。案例1返回“致命错误:所有goroutine都在睡着-死锁!”但是案例号有效。

案例1

func main(){

file, err := os.Open("/Users/sample/Downloads/wordlist")
if err != nil {
    log.Fatal(err)
}
lines := make (chan string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
    lines <- scanner.Text()
}
close(lines)

for line := range (lines) {
    fmt.Println(line)
}

}

案例#2

func main(){

file, err := os.Open("/Users/sample/Downloads/wordlist") 
if err != nil {
    log.Fatal(err)
}
lines := make (chan string)
go func() {
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines <- scanner.Text()
    }
    close(lines)
}()

for line := range (lines) {
    fmt.Println(line)
}

}

1 个答案:

答案 0 :(得分:1)

发送方阻塞,直到接收方在非缓冲通道中接收到该值为止。

在无缓冲的通道中,只有在必须有一些等待接收数据的接收器时,才会写入该通道。

例如:

queue := make(chan string)
queue <- "one" /* Here main function which is also a goroutine is blocked, because
there is no goroutine to receive the channel value, hence the deadlock*/
close(queue)
for elem := range queue {
    fmt.Println(elem)
}

这将导致死锁,而这正是您的 Case#1 代码中发生的情况。

现在,如果我们还有其他例行检查

queue := make(chan string)
go func() {
    queue <- "one" 
    close(queue)
}()
for elem := range queue {
    fmt.Println(elem)
}

这将起作用,因为main go例程在写数据到未缓冲的通道之前正在等待数据被消耗。

这确实是在您的第2种情况

中发生的

因此,简而言之,只有在有一些例程正在等待从通道读取时,才会发生对未缓冲通道的写入,否则写入操作将永远被阻塞并导致死锁。