golangで複数のスレッドから同じ変数を共有する方法は何ですか
Go言語では、goroutineとchannelを利用して並行処理における変数の共有を実現できます。
- Goルーチンとチャネルを使用する:
- goroutineを使用して複数のスレッドを作成し、それぞれが並行して実行できます。
- スレッド間の通信とデータ共有にはチャネルを使用し、スレッドセーフを確保する。
- チャネルを介して指定されたgoroutineにデータを送信し、チャネルから別のgoroutineからのデータを受信します。
- 次のコード例を参照してください。
- package mainimport (
“fmt”
“sync”
)var wg sync.WaitGroup
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Println(“Worker”, id, “started job”, j)
results <- j * 2 // 結果をresultsチャネルに送信
}
wg.Done()
}func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)// 3つのワーカーゴルーチンを作成
for w := 1; w <= 3; w++ {
wg.Add(1)
go worker(w, jobs, results)
}// jobsチャネルにタスクを送信
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)// resultsチャネルから処理結果を受信
for a := 1; a <= 9; a++ {
<-results
}// ワーカーゴルーチンの終了を待つ
wg.Wait()
} - 上記の例では、goroutineを使用して3つのワーカーを作成し、それらがjobsチャネルからタスクを受け取り、結果をresultsチャネルに送信します。メイン関数では、jobsチャネルに9つのタスクを送信し、resultsチャネルから9つの結果を受け取ります。
- syncパッケージのMutexを使用する:
- 共有変数のアクセスを同一時刻に1スレッドのみ許可するには、sync パッケージの Mutex 型を使用して共有変数を保護します。
- 共有変数にアクセスする前にLockメソッドを使用して共有変数をロックし、アクセスした後にUnlockメソッドを使用してアンロックします。
- 例として次のコードがあります。
- package mainimport (
“fmt”
“sync”
)var (
counter int
wg sync.WaitGroup
mutex sync.Mutex
)func worker() {
defer wg.Done()
for i := 0; i < 1000; i++ {
mutex.Lock()
counter++
mutex.Unlock()
}
}func main() {
wg.Add(2)
go worker()
go worker()
wg.Wait()
fmt.Println(“カウンタ:”, counter)
} - 共有変数counterを保護するためにsyncのMutex型を利用し、同期的に1つのスレッドのみがcounterにアクセスできるようにします。各ワーカー関数では、counterを使用する前にLockメソッドを利用してロックし、使用後はUnlockメソッドでロックを解除し、最後にcounterの値を出力します。
Goルーチンとチャネルを用いるか、排他制御を用いるかは、どちらでマルチスレッドの変数共有を実現しても構いません。具体的にどちらを用いるのかは、業務の場面と要求によって異なります。