現代のソフトウェア開発では、同時プログラミングが必要なスキルの 1 つになっています。 Go 言語は同時プログラミング用に特別に設計された言語で、組み込まれた Goroutines、Channels、Mutex およびその他のメカニズムにより、同時プログラミングの複雑さを大幅に簡素化できます。この記事では、Go 言語で並行プログラミングを実行する方法を紹介し、並行プログラムをより効率的に作成できるようにするための基本的な知識と実践的なスキルを提供します。
1. 同時プログラミングとは
通常、複数のファイルを同時に読み取る、複数のデータベースからデータを取得するなど、ソフトウェアで処理する複数のタスクがあります。並行プログラミングとは、プログラムの複数の部分を同時に実行して、タスク処理におけるプログラムの効率を向上させることです。並行プログラミングでは、複数のタスク間の競合を回避し、コードの正確性と保守性を確保する必要があります。
2. ゴルーチンとチャネル
Go 言語のゴルーチンとチャネルは、同時プログラミングを実装するための中心的なメカニズムです。
ゴルーチンは Go 言語の軽量スレッドです。キーワード go を使用して新しいゴルーチンを開始すると、プログラムは複数のタスクを同時に実行できます。 Goroutine は同じアドレス空間で実行でき、オペレーティング システムのスレッドのようなスレッドの作成、スレッドの破棄、およびコンテキストの切り替えのオーバーヘッドなしでスレッドを簡単に切り替えることができます。
チャネルは、Go 言語のゴルーチン間でメッセージをやり取りする方法です。チャネルを通じて、ゴルーチンはデータを安全に交換し、データ競合を回避できます。チャネルは、あるゴルーチンでメッセージ(データ)を送信し、別のゴルーチンでメッセージ(データ)を受信するパイプラインとみなすことができ、2 つのゴルーチン間の通信を実現します。
次は、ゴルーチンとチャネルを使用して同時計算を実装する簡単な例です:
package main import ( "fmt" "time" ) func main() { start := time.Now() c := make(chan int) go calculateSum(c) sum := <-c end := time.Now() fmt.Printf("Sum: %v Time: %v", sum, end.Sub(start)) } func calculateSum(c chan int) { sum := 0 for i := 0; i < 1000000000; i++ { sum += i } c <- sum }
この例では、新しいゴルーチンを開始して 0 から 100 million までの累積合計を計算し、次の値を渡します。結果はチャネル経由でメインのゴルーチンに送信されます。ゴルーチンとチャネルを使用すると、計算プロセス中に他のタスクを実行し、プログラムの効率を向上させることができます。
3. Mutex
同時プログラミングでは、データの競合やエラーを避けるために共有リソースへのアクセスを制御する必要があります。 Go 言語は、共有リソースへの安全なアクセス制御を実装するための Mutex (ミューテックス ロック) を提供します。 Mutex を使用すると、共有リソースに同時にアクセスできるのは 1 つの Goroutine だけであることが保証され、他の Goroutine はアクセスを続ける前に Mutex のロックが解除されるまで待機する必要があります。
次は、Mutex を使用して共有変数への安全なアクセスを確保する例です:
package main import ( "fmt" "sync" ) var count int var wg sync.WaitGroup var mutex sync.Mutex func main() { wg.Add(2) go increment() go increment() wg.Wait() fmt.Println("Count:", count) } func increment() { defer wg.Done() for i := 0; i < 1000000; i++ { mutex.Lock() count++ mutex.Unlock() } }
この例では、2 つの Goroutine を開始し、共有カウント変数を 100 万回操作してインクリメントします。各ゴルーチンが count 変数をインクリメントする前に、ミューテックスを使用して変数をロックし、同時に 1 つのゴルーチンだけがその変数にアクセスできるようにします。
4. セマフォを使用して同時実行性を制御する
Mutex を使用して共有リソースへのアクセスを制御するだけでなく、セマフォを使用して同時実行性を制御し、過剰な同時実行性によるシステムのクラッシュを防ぐこともできます。
セマフォは、オペレーティング システムの古典的な同時プログラミング テクノロジであり、一度に 1 つの Goroutine しかアクセスできない Mutex とは異なり、同時にアクセスされる共有リソースの数を制御できます。 Go 言語の sync パッケージは、同時 Goroutine の数を簡単に制御できるセマフォのサポートを提供します。
次は、セマフォを使用してゴルーチンの同時数を制御する例です:
package main import ( "fmt" "sync" ) var wg sync.WaitGroup var semaphore = make(chan struct{}, 2) // 最多允许2个Goroutine并发访问 func main() { for i := 0; i < 5; i++ { // 开启5个任务 wg.Add(1) go runTask(i) } wg.Wait() } func runTask(i int) { defer wg.Done() semaphore <- struct{}{} // 加锁,占用1个slot defer func() { <-semaphore // 解锁,释放1个slot }() fmt.Printf("Task %d start ", i) // do something fmt.Printf("Task %d end ", i) }
この例では、容量 2 のチャネルをセマフォとして使用します。最大 2 つの Goroutine を同時に実行できます。各ゴルーチンはタスクの開始時にセマフォ スロットを取得し、タスクの完了後にセマフォを解放します。すでに 2 つの Goroutine が実行されている場合、後続の Goroutine は、実行を開始する前に、既存のタスクが完了してセマフォを解放するのを待つ必要があります。
セマフォを使用すると、同時タスクの数を効果的に制御し、過剰なシステム同時実行によるリソース不足やクラッシュを回避できます。
5. 概要
同時プログラミングは、現代のソフトウェア開発において不可欠なスキルです。Go 言語は、シンプルで使いやすい Goroutines と Channels メカニズムに加え、Mutex や Channels などの高度なメカニズムを提供します。セマフォ: 効率的かつ安全な同時プログラミングを実現するには便利です。これらのメカニズムを使用する場合、プログラムの正確性と保守性を確保するために、データの競合と共有リソースの管理に注意を払う必要があります。この記事の導入により、同時プログラミングのためのゴルーチン、チャネル、ミューテックス、セマフォなどのメカニズムの使用方法をすでに理解し、効率的で安全な同時プログラムを作成できるようになっているはずです。
以上が同時に Golang を実行する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。