gpt4 book ai didi

go - 如何正确使用sync.Cond?

转载 作者:IT老高 更新时间:2023-10-28 13:02:19 25 4
gpt4 key购买 nike

我不知道如何正确使用 sync.Cond .据我所知,锁定 Locker 和调用条件的 Wait 方法之间存在竞争条件。这个例子在主 goroutine 的两行之间添加了一个人为的延迟来模拟竞态条件:

package main

import (
"sync"
"time"
)

func main() {
m := sync.Mutex{}
c := sync.NewCond(&m)
go func() {
time.Sleep(1 * time.Second)
c.Broadcast()
}()
m.Lock()
time.Sleep(2 * time.Second)
c.Wait()
}

[ Run on the Go Playground ]

这会立即引起 panic :

fatal error: all goroutines are asleep - deadlock!goroutine 1 [semacquire]:sync.runtime_Syncsemacquire(0x10330208, 0x1)    /usr/local/go/src/runtime/sema.go:241 +0x2e0sync.(*Cond).Wait(0x10330200, 0x0)    /usr/local/go/src/sync/cond.go:63 +0xe0main.main()    /tmp/sandbox301865429/main.go:17 +0x1a0

我做错了什么?如何避免这种明显的竞争条件?我应该使用更好的同步结构吗?


编辑:我意识到我应该更好地解释我试图在这里解决的问题。我有一个长时间运行的 goroutine,它下载一个大文件和许多其他 goroutine,它们需要在可用时访问 HTTP header 。这个问题比听起来更难。

我不能使用 channel ,因为只有一个 goroutine 会收到这个值。并且其他一些 goroutine 会在它们已经可用很久之后尝试检索它们。

下载器 goroutine 可以简单地将 HTTP header 存储在一个变量中,并使用互斥锁来保护对它们的访问。但是,这并没有为其他 goroutine 提供“等待”它们可用的方法。

我曾认为 sync.Mutexsync.Cond 一起可以实现这个目标,但似乎这是不可能的。

最佳答案

OP自己回答了,但没有直接回答原问题,我来贴一下如何正确使用sync.Cond

如果每次读写都有一个 goroutine,则实际上不需要 sync.Cond - 单个 sync.Mutex 就足以在它们之间进行通信。 sync.Cond 在多个阅读器等待共享资源可用的情况下可能很有用。

var sharedRsc = make(map[string]interface{})
func main() {
var wg sync.WaitGroup
wg.Add(2)
m := sync.Mutex{}
c := sync.NewCond(&m)
go func() {
// this go routine wait for changes to the sharedRsc
c.L.Lock()
for len(sharedRsc) == 0 {
c.Wait()
}
fmt.Println(sharedRsc["rsc1"])
c.L.Unlock()
wg.Done()
}()

go func() {
// this go routine wait for changes to the sharedRsc
c.L.Lock()
for len(sharedRsc) == 0 {
c.Wait()
}
fmt.Println(sharedRsc["rsc2"])
c.L.Unlock()
wg.Done()
}()

// this one writes changes to sharedRsc
c.L.Lock()
sharedRsc["rsc1"] = "foo"
sharedRsc["rsc2"] = "bar"
c.Broadcast()
c.L.Unlock()
wg.Wait()
}

Playground

话虽如此,如果情况允许,仍然推荐使用 channel 来传递数据。

注意:这里的sync.WaitGroup只用于等待goroutines完成执行。

关于go - 如何正确使用sync.Cond?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36857167/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com