仅当
sync.Cond
执行广播时,我才尝试在多个 go 例程中进行打印,但 go 例程陷入僵局。有什么方法可以改进下面的代码,有什么方法可以确定为什么这段代码会死锁?
package main
import (
"fmt"
"sync"
)
type Button struct {
Clicked *sync.Cond
}
func subscribe(cond *sync.Cond, btnMessage string, wg *sync.WaitGroup) {
defer wg.Done()
cond.L.Lock()
defer cond.L.Unlock()
cond.Wait()
fmt.Println(btnMessage)
}
func test6() {
var wg sync.WaitGroup
button := Button{
Clicked: sync.NewCond(&sync.Mutex{}),
}
wg.Add(3)
go subscribe(button.Clicked, "Button 1", &wg)
go subscribe(button.Clicked, "Button 2", &wg)
go subscribe(button.Clicked, "Button 3", &wg)
// Start the goroutines before broadcasting
button.Clicked.Broadcast()
wg.Wait()
}
func main() {
test6()
}
我收到以下死锁错误
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x466df7?)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/runtime/sema.go:62 +0x25
sync.(*WaitGroup).Wait(0x405399?)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/sync/waitgroup.go:139 +0x52
main.test6()
/home/runner/concurrency-in-go/main.go:36 +0x199
main.main()
/home/runner/concurrency-in-go/main.go:40 +0x17
goroutine 6 [sync.Cond.Wait]:
sync.runtime_notifyListWait(0xc000108050, 0x1)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/runtime/sema.go:517 +0x14c
sync.(*Cond).Wait(0x0?)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/sync/cond.go:70 +0x8c
main.subscribe(0xc000108040, {0x49962f, 0x8}, 0x0?)
/home/runner/concurrency-in-go/main.go:17 +0xbb
created by main.test6
/home/runner/concurrency-in-go/main.go:29 +0xdb
goroutine 7 [sync.Cond.Wait]:
sync.runtime_notifyListWait(0xc000108050, 0x2)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/runtime/sema.go:517 +0x14c
sync.(*Cond).Wait(0x0?)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/sync/cond.go:70 +0x8c
main.subscribe(0xc000108040, {0x499637, 0x8}, 0x0?)
/home/runner/concurrency-in-go/main.go:17 +0xbb
created by main.test6
/home/runner/concurrency-in-go/main.go:30 +0x12f
goroutine 8 [sync.Cond.Wait]:
sync.runtime_notifyListWait(0xc000108050, 0x0)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/runtime/sema.go:517 +0x14c
sync.(*Cond).Wait(0x0?)
/nix/store/akhjsmrrsakcnj8x3xgygvizhccbyn0v-go-1.19.3/share/go/src/sync/cond.go:70 +0x8c
main.subscribe(0xc000108040, {0x49963f, 0x8}, 0x0?)
/home/runner/concurrency-in-go/main.go:17 +0xbb
created by main.test6
/home/runner/concurrency-in-go/main.go:31 +0x185
exit status 2
在你的 goroutine 初始化之前你就已经开始广播了。所以你最终会广播然后再次等待。如果您在主线程中插入睡眠,您可以看到它开始工作。
只有当满足某些条件时,你才应该在 goroutine 中等待。根据您的实际用例,您可能会考虑不同的同步原语。