sync.Cond
を正しく使用する方法がわかりません。私が知る限り、ロッカーをロックして条件のWaitメソッドを呼び出す間に競合状態が存在します。この例では、競合状態をシミュレートするために、メインゴルーチンの2つのライン間の人工的な遅延を追加します。sync.Condを正しく使用するには?
package main
import (
"sync"
"time"
)
func main() {
m := sync.Mutex{}
c := sync.NewCond(&m)
go func() {
time.Sleep(1 * time.Second)
c.Broadcast()
}()
m.Lock()
time.Sleep(2 * time.Second)
c.Wait()
}
をこれはすぐにパニックが発生します。
fatal error: all goroutines are asleep - deadlock! goroutine 1 [semacquire]: sync.runtime_Syncsemacquire(0x10330208, 0x1) /usr/local/go/src/runtime/sema.go:241 +0x2e0 sync.(*Cond).Wait(0x10330200, 0x0) /usr/local/go/src/sync/cond.go:63 +0xe0 main.main() /tmp/sandbox301865429/main.go:17 +0x1a0
何私は間違っている?この明白な競合状態を避けるにはどうすればよいですか?私は使用する必要がありますより良い同期の構成はありますか?
編集:私はより良い私はここで解決しようとしている問題を説明している必要があります実現。私は長いファイルをダウンロードし、利用可能なときにHTTPヘッダーにアクセスする必要がある他のいくつかのgoroutineをダウンロードする長年のgoroutineを持っています。この問題はそれよりも難しいです。
チャネルを使用することはできません.1つのゴルーチンだけが値を受け取るためです。そして、他のgoroutinesのいくつかは、すでに利用可能になってから長い間ヘッダを取得しようとしています。
ダウンローダのgoroutineは、HTTPヘッダーを変数に格納し、mutexを使用してそのアクセスを保護できます。しかし、これは、他のゴルーチンが利用可能になるのを待つ方法を提供しません。
私はsync.Mutex
とsync.Cond
の両方がこの目標を達成できると考えていましたが、これは不可能と思われます。
ことができない場合ゴルーチンを起動する前に、ミューテックスをロックしますか?たとえば、Wait()を呼び出す他のゴルーチンがあるかもしれません。 –
Broadcastが呼び出されたときに他のゴルーチンが通知されることはありません。それはうまくいく - しかし、私たちはどちらも言及していない - 通常状態はいくつかの状態に関連しています。そして、待つこと - 私はこの状態にシステムがある間、私は続けることができません。ブロードキャストは状態が変わったことを意味します。待っていた人は誰でも続けることができるかどうかを確認する必要があります。両方のgoroutineで計算されるものと、なぜ彼らが互いに通信しなければならないのかをより正確に記述してください。 – lofcek
申し訳ありませんが、私は元の質問でさらに詳しく説明する必要があります。私は何をしようとしているのかを正確に記述した編集を追加しました。 –