为什么我在这段 Golang 代码中遇到了死锁问题?

huangapple go评论76阅读模式
英文:

Why do I run into a deadlock with this Golang code?

问题

我对Golang还不太熟悉。你提供的代码是为了练习而写的,但遇到了一个死锁的运行时错误消息:

package main

import (
	"fmt"
)

func system(WORKERS int) {
	fromW := make(chan bool)
	toW := make(chan bool)
	for i := 0; i != WORKERS; i++ {
		go worker(toW, fromW)
	}
	coordinator(WORKERS, fromW, toW)
}

func coordinator(WORKERS int, in, out chan bool) {
	result := true
	for i := 0; i != WORKERS; i++ {
		result = result && <-in
	}
	for i := 0; i != WORKERS; i++ {
		out <- result
	}
	fmt.Println("%t", result)
}

func worker(in, out chan bool) {
	out <- false
	<-in
}

func main() {
	system(2)
}

然而,如果我将第19行的&&操作符的操作数交换为:

result = <-in && result

那么代码将正常工作,不会返回任何错误消息。我该如何解释这种行为?我是否漏掉了什么?我使用的操作系统是Windows 10,Golang版本是1.8.3。

非常感谢您的帮助。

英文:

I am quite new to Golang. I wrote the following code for practice and ran into a run-time error message of a deadlock:

package main

import (
    &quot;fmt&quot;
)

func system(WORKERS int) {
    fromW := make(chan bool)
    toW := make(chan bool)
    for i := 0; i != WORKERS; i++ {
	    go worker(toW, fromW)
    }
    coordinator(WORKERS, fromW, toW)
}

func coordinator(WORKERS int, in, out chan bool) {
    result := true
    for i := 0; i != WORKERS; i++ {
	    result =  result &amp;&amp; &lt;-in
    }
    for i := 0; i != WORKERS; i++ {
	    out &lt;- result
    }
    fmt.Println(&quot;%t&quot;, result)
}

func worker(in, out chan bool) {
    out &lt;- false
    &lt;-in
}

func main() {
    system(2)
}

However, if I swap the operands of && in line 19 to have

result =  &lt;-in &amp;&amp; result,

the code works properly without returning any error messages. How can I explain this behaviour? Am I missing anything here? The OS I use is Windows 10, and the Golang version is 1.8.3.

Thank you very much in advance.

答案1

得分: 6

如您可以在这里看到,&& 的右操作数是有条件地进行评估的。

这意味着只有在 result 为真时,result = result && <-in 才会评估 <-in。因此,协调器只从该通道读取一个 false,并跳过从其他工作器读取消息的步骤。如果您交换 && 的操作数位置,那么 <-in 将每次都会被评估,死锁问题就会消失。

英文:

As you can see here, the right operand of &amp;&amp; is evaluated conditionally.

This means that result = result &amp;&amp; &lt;-in will only evaluate &lt;-in if result is true. So, the coodrinator reads only one false from that channel, and skips reading messages from the other workers. If you switch the operands of &amp;&amp; places, then the &lt;-in will evaluate every time and the deadlock goes away.

huangapple
  • 本文由 发表于 2017年8月22日 15:54:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/45811933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定