Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明
マルチコア プロセッサの普及とコンピュータのパフォーマンスの継続的な向上に伴い、複数のプロセッサ コアを最大限に活用する方法並列コンピューティングは開発者にとって重要な問題に直面しており、懸念事項となっています。同時プログラミングは、この問題を解決するための重要なテクノロジーの 1 つです。 Golang では、同時プログラミングを実装するためにゴルーチンとチャネルが広く使用されています。その中でもゴルーチンは、高い同時実行性のタスク処理を実現できる軽量なスレッドです。複数のゴルーチン間の正しい連携を確保するには、同期および相互排他メカニズムが重要な役割を果たします。
1. ゴルーチンの基本概念
Golang では、ゴルーチンは他のゴルーチンと同時に実行できる軽量のスレッドです。 Goroutine は、従来のスレッドよりも作成および破棄にかかるリソースのコストが少なく、システム リソースをより効率的に利用できます。
Goroutine はキーワード「go」を使用して作成されます。サンプル コードは次のとおりです。
package main import ( "fmt" "time" ) func task1() { for i := 0; i < 5; i++ { fmt.Println("Task 1:", i) time.Sleep(time.Millisecond * 500) } } func task2() { for i := 0; i < 5; i++ { fmt.Println("Task 2:", i) time.Sleep(time.Millisecond * 500) } } func main() { go task1() go task2() time.Sleep(time.Millisecond * 3000) }
上記のコードでは、キーワード「go」によって 2 つのゴルーチンが作成され、task1()
と task2()## が実行されます。 # それぞれの関数。
main() 関数では、
time.Sleep() 関数を通じて 3 秒間待機し、ゴルーチンが実行を完了するのに十分な時間を確保します。
実際の同時プログラミングでは、複数の Goroutine が特定のリソースを共有する必要がある場合があります。現時点では、リソースへの正しいアクセスを保証するために、同期および相互排他メカニズムが必要です。
WaitGroup は、Goroutine のグループの実行が完了するのを待つために使用されます。その機能は Java の CountDownLatch に似ています。サンプル コードは次のとおりです。
package main import ( "fmt" "sync" "time" ) func task(i int, wg *sync.WaitGroup) { defer wg.Done() fmt.Println("Task", i) time.Sleep(time.Millisecond * 500) } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go task(i, &wg) } wg.Wait() fmt.Println("All tasks finished") }
wg が
sync.WaitGroup を通じて作成されます。各ゴルーチンが実行される前に
wg.Add(1) を呼び出して、待機グループ カウンターを 1 ずつインクリメントし、待機する必要があるタスクがあることを示します。各ゴルーチンが実行された後、
wg.Done() を呼び出して待機グループ カウンターを 1 減算し、タスクが完了したことを示します。最後に、
wg.Wait() を通じてすべてのタスクが完了するまで待ちます。
Mutex はミューテックス ロックで、同時に 1 つの Goroutine のみがアクセスできる共有リソースを保護するために使用されます。サンプル コードは次のとおりです。
package main import ( "fmt" "sync" "time" ) var count int var mutex sync.Mutex func task(i int, wg *sync.WaitGroup) { defer wg.Done() mutex.Lock() defer mutex.Unlock() count++ fmt.Println("Task", i, "count:", count) time.Sleep(time.Millisecond * 500) mutex.Lock() defer mutex.Unlock() count-- } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go task(i, &wg) } wg.Wait() fmt.Println("All tasks finished") }
mutex が
sync.Mutex を通じて作成されます。各ゴルーチンでは、共有リソースへのアクセスは、
mutex.Lock() と
mutex.Unlock() のペアを呼び出すことによって保護されます。実際のアプリケーションでは、保護する必要がある共有リソースを構造体に格納し、構造体のミューテックス ロックを通じて共有リソースへのアクセスを制御できます。
Once は、プログラムの実行中に特定のコード部分が 1 回だけ実行されるようにするために使用されます。サンプル コードは次のとおりです。
package main import ( "fmt" "sync" ) var once sync.Once func task() { fmt.Println("Task executed") } func main() { for i := 0; i < 5; i++ { once.Do(task) } }
sync.Once を通じて Once オブジェクト
once が作成されます。各ゴルーチンで
once.Do(task) を呼び出すと、プログラム実行時間全体で
task() 関数が 1 回だけ実行されるようになります。
Mutex は、相互排他を実装するために使用することもできます。サンプル コードは次のとおりです。
package main import ( "fmt" "sync" "time" ) var count int var mutex sync.Mutex func task(i int, wg *sync.WaitGroup) { defer wg.Done() mutex.Lock() defer mutex.Unlock() fmt.Println("Task", i) time.Sleep(time.Millisecond * 500) } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go task(i, &wg) } wg.Wait() fmt.Println("All tasks finished") }
mutex.Lock() と
mutex.Unlock() を呼び出して、 Goroutine は
task() 関数を実行し、共有リソースにアクセスします。
この記事の導入部を通じて、Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムについて学びました。実際のアプリケーションでは、同期および相互排他メカニズムが、複数のゴルーチン間の正しい連携を確保するための鍵となります。 WaitGroup、Mutex、RWMutex などの同期および相互排他メカニズムを適切に使用すると、共有リソースへの正しいアクセスが確保され、効率的な同時プログラミングが実現します。
以上がGolang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。