Golang における同期メカニズムとパフォーマンスのボトルネック最適化ソリューション
package main import ( "fmt" "sync" ) var ( count int lock sync.Mutex ) func increment() { lock.Lock() defer lock.Unlock() count++ } func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() increment() }() } wg.Wait() fmt.Println(count) }
2.2 条件変数 (Cond)
条件変数は、コルーチン間で通信し、コルーチンの待機およびウェイクアップ メカニズムを実装するために使用されます。 。コルーチンが特定の条件を満たした場合、条件変数を使用して他のコルーチンに通知できます。以下は、条件変数を使用したサンプル コードです。
package main import ( "fmt" "sync" ) var ( ready bool cond *sync.Cond ) func init() { cond = sync.NewCond(&sync.Mutex{}) } func printNumbers() { cond.L.Lock() defer cond.L.Unlock() for !ready { cond.Wait() } fmt.Println("1 2 3 4 5") } func main() { go printNumbers() cond.L.Lock() ready = true cond.Signal() cond.L.Unlock() }
2.3 読み取り/書き込みロック (RWMutex)
読み取り/書き込みロックを使用すると、並行プログラムのパフォーマンスをさらに向上させることができます。読み取りが多く書き込みが少ないシナリオでは、読み取り/書き込みロックを使用すると、複数のコルーチンが共有リソースを同時に読み取ることができる一方で、書き込み操作を実行できるのは 1 つのコルーチンだけになります。以下は、読み取り/書き込みロックを使用するサンプル コードです。
package main import ( "fmt" "sync" ) var ( count int lock sync.RWMutex ) func read() { lock.RLock() defer lock.RUnlock() fmt.Println(count) } func write() { lock.Lock() defer lock.Unlock() count++ } func main() { var wg sync.WaitGroup wg.Add(10) for i := 0; i < 5; i++ { go func() { defer wg.Done() read() }() go func() { defer wg.Done() write() }() } wg.Wait() }
3.1 ロックの粒度を下げる
ミューテックス ロックを使用する場合、ロックの粒度を最小限に抑え、必要なクリティカル セクション コード セグメントのみをロックできます。これにより、ロックの競合が軽減されます。読み取り/書き込みロックを使用する場合、並列読み取りの特性を最大限に活用するために、実際の状況に応じて読み取りロックまたは書き込みロックを選択できます。
3.2 ロックフリーのデータ構造の使用
高い同時実行性のシナリオでは、アトミック パッケージのアトミック操作関数など、ロックフリーのデータ構造の使用を検討できます。これらの関数は、データの一貫性を確保するためにロックを使用せずにいくつかのアトミック操作を提供します。たとえば、一貫したカウントを確保するには、ミューテックスの代わりに atomic.AddInt64() を使用します。
3.3 ミューテックス ロックの代わりにチャネルを使用する
チャネルは、データ アクセスの順序と一貫性を確保するための同期メカニズムとして使用できます。一部のシナリオでは、チャネルを使用すると、ミューテックス ロックの明示的な使用が回避され、ロックの競合が軽減されます。ただし、ブロッキングやメモリ リークを避けるために、チャネル容量とパフォーマンスのオーバーヘッドに注意を払う必要があります。
以上がGolang の同期メカニズムとパフォーマンスのボトルネック最適化ソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。