dstwfcz1377 2016-04-28 18:33
浏览 99
已采纳

如何使用sync.Cond对在无限for循环上运行的goroutine进行单元测试?

I am trying to unit test a channel that runs on an infinite for loop. I think I've found a way to do it, but I'm not sure if it's a valid way to use conditional variables. Also I'm not sure if this approach is prone to a race condition. Since the for loop is running on its own goroutine, is it possible the channel would be drained by the time I get to "cond.Wait()?" If this happened would I hang forever? In all the examples I've seen using conditional variables they are usually accompanied by a for loop surrounding the wait. Do I need this here? My question: is there anything wrong with the approach I'm using here? Is this a valid/idiomatic use of conditional variables?

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()
    }
}
  • 写回答

1条回答 默认 最新

  • doumi7861 2016-04-28 18:53
    关注

    To my mind you are right in all of your assumptions. To avoid channel draining just use

    close(doStuffChan)
    

    instead of doStuffChan <- true, because you can receive nil from closed channel forever. Them surround Wait with loop to check before cond been true since it's a condition in most cases. If you don't want to close channel guard signalling in channel and broadcasting with Lock, which make operation precedence deterministic.

    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()
        }
    }
    

    See it works https://play.golang.org/p/1S6VW7nIoV Both versions are threadsafe however.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?