【问题标题】:Go: Reading a file, goroutine deadlockGo:读取文件,goroutine死锁
【发布时间】:2019-09-07 05:04:45
【问题描述】:

我有两组代码 - 读取包含随机文本行的文件,并将每一行加载到一个通道。我无法理解为什么返回错误。但另一个没有。案例 #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 阻止发送到lines,因为没有准备好的接收器。因为goroutine被阻塞了,所以代码不会在lines上执行receive。僵局。恐慌。繁荣! Go: fatal error: all goroutines are asleep - deadlock 的可能重复项。

标签: go


【解决方案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 代码中发生的情况。

现在如果我们有其他 goroutine

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

这会起作用,因为主 go 例程正在等待数据被消耗,然后写入发生在无缓冲通道上。

这正是发生在您的案例#2

所以简而言之,只有当有一些例程等待从通道读取时才会写入到无缓冲通道,否则写入操作将永远阻塞并导致死锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多