我正在尝试对在无限循环上运行的通道进行单元测试。我想我已经找到了一种方法,但我不确定它是否是使用条件变量的有效方法。此外,我不确定这种方法是否容易出现竞争状况。因为for循环在它自己的goroutine上运行,所以当我到达" cond.Wait()时,通道是否可能被耗尽?"如果发生这种情况,我会永远挂起吗在我看过使用条件变量的所有例子中,它们通常伴随着围绕等待的for循环。我在这需要吗?我的问题:我在这里使用的方法有什么问题吗?这是条件变量的有效/惯用吗?
package main
import (
"fmt"
"sync"
)
var doStuffChan chan bool
var cond *sync.Cond
var result string
func main() {
doStuffChan = make(chan bool, 10)
cond = &sync.Cond{L: &sync.Mutex{}}
go startDoStuffLoop()
doStuffChan <- true
cond.L.Lock()
cond.Wait()
cond.L.Unlock()
fmt.Println(result)
}
func startDoStuffLoop() {
for {
<-doStuffChan
result = "success"
cond.Broadcast()
}
}
答案 0 :(得分:2)
在我看来,你的所有假设都是正确的。为避免渠道耗尽,请使用
close(doStuffChan)
而不是doStuffChan <- true
,因为您可以永久地从封闭频道收到nil。
他们围绕等待循环检查cond之前是真的,因为它在大多数情况下是一个条件。如果您不想在频道中关闭频道保护信令并使用Lock进行广播,这会使操作优先于确定性。
func main() {
doStuffChan = make(chan bool)
cond = &sync.Cond{L: &sync.Mutex{}}
go startDoStuffLoop()
cond.L.Lock()
doStuffChan <- true
cond.Wait()
cond.L.Unlock()
fmt.Println(result)
}
func startDoStuffLoop() {
for {
<-doStuffChan
result = "success"
cond.L.Lock()
cond.Broadcast()
cond.L.Unlock()
}
}
看到它有效https://play.golang.org/p/1S6VW7nIoV但两个版本都是线程安全的。