2016-04-28 17 views
0

我正在嘗試單元測試在無限循環上運行的通道。我想我已經找到了一種方法來做到這一點,但我不確定這是否是使用條件變量的有效方法。此外,我不確定這種方法是否容易出現競爭狀況。由於for循環在其自己的goroutine上運行,當我到達「cond.Wait()?」時,通道是否可能會流失?如果這發生,我會永遠掛?在所有我見過的使用條件變量的例子中,它們通常伴隨着圍繞等待的for循環。我需要這裏嗎?我的問題:我在這裏使用的方法有什麼問題嗎?這是條件變量的有效/習慣用法嗎?如何使用sync.Cond測試在無限for循環上運行的goroutine?

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

回答

2

在我看來,你對所有的假設都是正確的。爲了避免排水通道只使用

close(doStuffChan) 

代替doStuffChan <- true,因爲你永遠可以接收來自封閉的通道爲零。 它們環繞等待循環在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然而這兩個版本都是線程安全的。

+0

如果我關閉了doStuffChan,它就不起作用了。另外,我需要保持頻道開放以接收未來事件。基本上我需要一種方法來檢查doStuffLoop的一次迭代是否運行。但是渠道應該爲未來的運營保持開放。 https://play.golang.org/p/gsOwifVkOZ – circuitry

+0

此外,我仍然不確定是否有可能在這裏遇到競賽狀況。 – circuitry

+0

剛剛更新了答案 – Uvelichitel