英文:
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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论