英文:
why my golang goroutine code get deadlocked
问题
我尝试使用通道和goroutine编写一些代码,但是出现了死锁,为什么会这样呢?我在使用WaitGroup方面有什么错误吗?我感到很困惑...
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string, 2)
wg.Add(1)
go makeChanStr("yeye", chan1, chan3)
wg.Add(1)
go makeChanStr("okok", chan2, chan3)
wg.Wait()
close(chan3)
println(<-chan1)
println(<-chan2)
for chs := range chan3 {
println(chs)
}
}
func makeChanStr(s string, c1 chan string, c2 chan string) {
defer wg.Done()
c1 <- "get " + s
c2 <- "same value"
fmt.Printf("execute ok %s", s)
}
Stackoverflow不让我提交问题......所以我只能添加一些文本.....
英文:
I try to write some goroutine with channel, but get deadlocked, why?
Am I doing wrong with WaitGroup, so confused...
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string, 2)
wg.Add(1)
go makeChanStr("yeye", chan1, chan3)
wg.Add(1)
go makeChanStr("okok", chan2, chan3)
wg.Wait()
close(chan3)
println(<-chan1)
println(<-chan2)
for chs := range chan3 {
println(chs)
}
}
func makeChanStr(s string, c1 chan string, c2 chan string) {
defer wg.Done()
c1 <- "get " + s
c2 <- "same value"
fmt.Printf("execute ok %s", s)
}
Stackoverflow just don't let me submit the question.......so I just have to add some text.....
答案1
得分: 4
主要是在wg.Wait()
的代码块上,它等待这两个goroutine完成(因为有wg.Add(1)
和wg.Done()
)。
go makeChanStr("yeye", chan1, chan3)
go makeChanStr("okok", chan2, chan3)
但它们在chan1
(或chan2
)上阻塞,因为它是一个无缓冲通道。
chan1 := make(chan string)
尝试将chan1
和chan2
更改为带缓冲的通道:
chan1 := make(chan string, 1)
chan2 := make(chan string, 1)
英文:
main block on wg.Wait()
, which wait this two go routines to finish(because of wg.Add(1)
and wg.Done()
)
go makeChanStr("yeye", chan1, chan3)
go makeChanStr("okok", chan2, chan3)
but they block on chan1
(or chan2
) , because it's an unbuffer channel.
chan1 := make(chan string)
try change chan1
and chan2
to buffer channels:
chan1 := make(chan string,1)
chan2 := make(chan string,1)
答案2
得分: 1
这段代码在主goroutine中的wg.Wait()
和工作goroutine中写入c1
时会阻塞。为了避免这种情况,可以在wg.Wait()
之前从c1
和c2
中读取数据,从而解除工作goroutine的阻塞,它们将不会在写入缓冲的c3
时阻塞。结果是wg.Done()
将被调用,wg.Wait()
也不会阻塞主goroutine。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string, 2)
wg.Add(1)
go makeChanStr("yeye", chan1, chan3)
wg.Add(1)
go makeChanStr("okok", chan2, chan3)
println(<-chan1)
println(<-chan2)
wg.Wait()
close(chan3)
for chs := range chan3 {
println(chs)
}
}
func makeChanStr(s string, c1 chan string, c2 chan string) {
defer wg.Done()
c1 <- "get " + s
c2 <- "same value"
fmt.Printf("execute %s\n", s)
}
英文:
This code blocks on wg.Wait()
in main goroutine and writing to c1
in workers. To avoid it - read from c1
and c2
prior to wg.Wait()
thus unblock workers and they will not block on writing to buffered c3
. As a result wg.Done()
will be called and wg.Wait()
will not block main goroutine as well.
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string, 2)
wg.Add(1)
go makeChanStr("yeye", chan1, chan3)
wg.Add(1)
go makeChanStr("okok", chan2, chan3)
println(<-chan1)
println(<-chan2)
wg.Wait()
close(chan3)
for chs := range chan3 {
println(chs)
}
}
func makeChanStr(s string, c1 chan string, c2 chan string) {
defer wg.Done()
c1 <- "get " + s
c2 <- "same value"
fmt.Printf("execute %s\n", s)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论