問題を理解する
sync.Cond を使用する場合、次のことが重要です。ロックと Wait メソッドの呼び出しの間の潜在的な競合状態に注意してください。提供された例では:
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() }
メインの goroutine は、ミューテックスのロックと c.Wait() の呼び出しの間に意図的に遅延を導入します。これは、実行時にデッドロック パニックを引き起こす競合状態をシミュレートします。
競合状態の解決
この問題を回避するには、c を呼び出す前に明示的にロックを取得することが不可欠です。 。待って()。そうすることで、対応するミューテックスがロックされている場合にのみ Cond が待機するようになります。
sync.Cond を使用する場合
sync.Cond が適切かどうかの判断シナリオの同期プリミティブも同様に重要です。複数のリーダーが共有リソースが利用可能になるのを待つシナリオには適していますが、ゴルーチン間の 1 対 1 の書き込みおよび読み取り操作には、より単純な sync.Mutex で十分かもしれません。
チャネルを代替
場合によっては、チャネルは sync.Cond と比較してより効率的なデータ交換方法を提供します。たとえば、上記の例では、HTTP ヘッダーが利用可能になったときに通知するためにチャネルを使用できます。このアプローチにより、ロックと待機の必要がなくなり、パフォーマンスが向上します。
例: sync.Cond の使用
sync.Cond が推奨されるアプローチの場合は、次の例:
var sharedRsc = make(map[string]interface{}) func main() { var wg sync.WaitGroup wg.Add(2) m := sync.Mutex{} c := sync.NewCond(&m) go func() { c.L.Lock() for len(sharedRsc) == 0 { c.Wait() } fmt.Println(sharedRsc["rsc1"]) c.L.Unlock() wg.Done() }() go func() { c.L.Lock() for len(sharedRsc) == 0 { c.Wait() } fmt.Println(sharedRsc["rsc2"]) c.L.Unlock() wg.Done() }() c.L.Lock() sharedRsc["rsc1"] = "foo" sharedRsc["rsc2"] = "bar" c.Broadcast() c.L.Unlock() wg.Wait() }
結論
sync.Cond はデータ共有と同期のためのソリューションを提供しますが、このプリミティブの適合性を注意深く検討することが重要です。特定の要件。潜在的な競合状態と代替同期メカニズムを理解すると、Go アプリケーションで sync.Cond を効果的に利用するのに役立ちます。
以上がGo で sync.Cond を使用するときにデッドロックを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。