2015-11-27 3 views
1

Является ли метод Wait()sync.Cond безопасным, если в соответствии с документацией он выполняет сначала Unlock()?Вызывает метод `Wait()` `sync.Cond` одновременно, безопасно?

Предположим, мы проверяем на состояние должны быть выполнены:

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) имеет фиксирующую его собственной? Или быть атомным?

ответ

2

Да, это безопасно вызывать Wait даже когда он называет L.Unlock() первый, но очень важно, чтобы вы приобрели замок перед вызовом Wait и перед проверкой вашего состояния, так как в этой ситуации, и не являются поточно.

Wait атомарно разблокирует c.Lи приостанавливает выполнение вызывающего goroutine. Позже возобновление исполнения, Wait замки c.L перед возвратом.

  1. goroutine, который вызывает Wait приобретенную замок, проверил состояние и нашел его неудовлетворительным.
  2. Теперь он ждет, но для того, чтобы разрешить изменения состояния, необходимого для его блокировки. Wait делает это автоматически для вас, а затем приостанавливает передачу.
  3. Теперь изменения состояния могут произойти, и в итоге горутин пробуждается Broadcast или Signal. Затем он получает блокировку для проверки состояния еще раз (это должно происходить один за другим для каждого ожидающего goroutine, иначе невозможно было бы сообщить, сколько горутов свободно работает сейчас).
+0

Так что 'Unlock()' не разблокирует уже заблокированный 'Cond' в другом' goroutine'? –

+0

Глупый мне! Я уже приобрел блокировку перед вызовом 'Wait()'! –