并发调用`sync.Cond`的`Wait()`方法安全吗?

Is Calling the `Wait()` method of `sync.Cond` Concurrently, Safe?

根据文档调用 sync.CondWait() 方法是否安全,它首先执行 Unlock()

假设我们正在检查要满足的条件:

func sample() {
    cond = &sync.Cond{L: &sync.Mutex{}} // accessible by other parts of program

    go func() {
        cond.L.Lock()
        for !condition() {
            cond.Wait()
        }
        // do stuff ...
        cond.L.Unlock()
    }()

    go func() {
        cond.L.Lock()
        mutation()
        cond.L.Unlock()

        cond.Signal()
    }()
}

并且:

func condition() bool {
    // assuming someSharedState is a more complex state than just a bool
    return someSharedState
}

func mutation() {
    // assuming someSharedState is a more complex state than just a bool
    // (A) state mutation on someSharedState
}

既然 Wait() 执行了 Unlock,(A) 应该有自己的锁定吗?或者是原子的?

是的,调用 Wait 是安全的,即使它先调用 L.Unlock() 但在调用 Wait 之前和检查您的条件之前获取锁是必不可少的,因为,这种情况,两者都不是线程安全的。

Wait atomically unlocks c.L and suspends execution of the calling goroutine. After later resuming execution, Wait locks c.L before returning.

  1. 调用Wait的goroutine获取了锁,检查了条件,发现不满足。
  2. 现在它在等待,但为了允许条件发生变化,它需要将锁还给它。 Wait 会自动为您执行此操作,然后挂起 goroutine。
  3. 现在可以发生条件变化,最终 goroutine 被 BroadcastSignal 唤醒。然后它获取锁以再次检查条件(这必须对每个等待的 goroutine 逐一发生,否则将无法知道现在有多少 goroutine 运行 自由使用)。