sync.Cond 是一个事件告诉,相似于java中的conditional 或者 wait/notify 机制。

它有一个重要的作用是,协程之间通过锁进行协调的时候,其中一个协程期待的时候,能够开释锁和资源,并且可能及时实现筹备工作。

比方经典的生产者生产,例如有一个队列,只有大小为1,生产者须要期待消费者实现生产,能力持续寄存。

package mainimport (    "fmt"    "sync"    "time")func main() {    cond := sync.NewCond(&sync.Mutex{})    msg := make([]string, 1)    var sended bool    go func() {        for {            time.Sleep(time.Second)            cond.L.Lock()            for !sended {                cond.Wait()            }            fmt.Printf("get msg %s\n" , msg[0])            sended = false            cond.Signal()            cond.L.Unlock()        }    }()    go func() {        for {            time.Sleep(time.Second)            cond.L.Lock()            for sended {                cond.Wait()            }            s := fmt.Sprint("time is ", time.Now().String())            msg[0]= s            fmt.Printf("put in msg:%s\n", s)            sended = true            cond.Signal()            cond.L.Unlock()                }    }()    time.Sleep(time.Second* 50)}

它的模式是

cond.L.Lock()for 判断条件 {    cond.Wait()}//执行工作cond.L.Unlock()

另外一个中央当条件满足时,就会cond.Signal(),然而signal办法只会唤醒一个协程,如果实在场景下是多个协程中一部分须要被唤醒,就必须要用 cond.Broadcast(), 相当于notifyAll()。

通常唤醒的中央,也是在应用临界区的资源,所以唤醒的中央也会写成如下模式

cond.L.Lock()// 执行工作cond.Broadcast()cond.L.Unlock()

相比拟于 notify 的用法宽松的中央是, Broadcast 和Signal 办法不须要放在锁内。而wait条件因为曾经包装在for循环内,就能够释怀的Broadcast

因为下面的示例是相互唤醒,因而写法如下:

cond.L.Lock()for 判断条件 {    cond.Wait()}cond.Broadcast()cond.L.Unlock()

尽管channel也能够用于这个场景,然而cond 在一些简化的场景下,能够获得较好的性能。