1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goで学ぶ並行処理の基礎と実践

Posted at

はじめに

Go言語の特徴の一つに「並行処理の簡潔さ」が挙げられます。本記事では、Goの並行処理について基礎から学び、実際に役立つサンプルコードを解説していきます。

並行処理とは?

並行処理(Concurrency)は、複数のタスクを同時に進行させる技術です。Goでは、goroutine と呼ばれる軽量スレッドを用いて並行処理を実現します。

例えば、以下のようなシナリオがあるとします:

  • Webサーバーが同時に複数のクライアントリクエストを処理する。
  • 大量のデータを並行して処理して、高速化を図る。

こうした処理を簡潔に実現できるのが、Goのgoroutineとチャネル(channel)です。

基本:goroutineの使い方

Goでgoroutineを使うのは非常に簡単です。goキーワードを使うだけで関数を並行実行できます。

コード例

package main

import (
	"fmt"
	"time"
)

func sayHello() {
	for i := 0; i < 5; i++ {
		fmt.Println("Hello, World!")
		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	go sayHello() // goroutineで実行
	for i := 0; i < 5; i++ {
		fmt.Println("Main Function")
		time.Sleep(300 * time.Millisecond)
	}
}

この例では、sayHello関数がgoroutineとして並行実行され、メイン関数の処理と同時に動作します。

実践:チャネル(channel)の活用

goroutine間でデータをやり取りするには、チャネル(channel)が便利です。

チャネルの基礎

チャネルはデータを送受信するための仕組みで、make(chan 型)で生成します。

package main

import "fmt"

func sendData(ch chan int) {
	for i := 1; i <= 5; i++ {
		ch <- i // データを送信
	}
	close(ch) // チャネルを閉じる
}

func main() {
	ch := make(chan int) // チャネルを作成
	go sendData(ch)      // goroutineでデータを送信

	for data := range ch { // チャネルからデータを受信
		fmt.Println(data)
	}
}

このコードでは、sendData関数がチャネルを通じてデータを送信し、main関数がそれを受け取ります。

よくある課題と解決策

1. デッドロック(Deadlock)

チャネルを正しく管理しないと、デッドロックが発生することがあります。デッドロックは、goroutineが互いに待機し続ける状態です。

解決策

  • チャネルを必ず閉じる。
  • バッファ付きチャネルを利用する。
ch := make(chan int, 2) // バッファサイズを指定
ch <- 1
ch <- 2
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2

応用:ワーカー(Worker)パターン

並行処理で効率よくタスクを処理するには、ワーカーパターンが有用です。以下にタスクをワーカーに分散させる例を示します。

package main

import (
	"fmt"
	"time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
	for job := range jobs {
		fmt.Printf("Worker %d started job %d\n", id, job)
		time.Sleep(time.Second) // ジョブ処理に1秒
		fmt.Printf("Worker %d finished job %d\n", id, job)
		results <- job * 2
	}
}

func main() {
	const numJobs = 5
	jobs := make(chan int, numJobs)
	results := make(chan int, numJobs)

	// ワーカーを3つ作成
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results)
	}

	// ジョブを送信
	for j := 1; j <= numJobs; j++ {
		jobs <- j
	}
	close(jobs)

	// 結果を受信
	for a := 1; a <= numJobs; a++ {
		fmt.Println("Result:", <-results)
	}
}

まとめ

Go言語の並行処理は、goroutinechannelを用いることで、簡潔かつ強力に実現できます。本記事で紹介した基礎を押さえることで、実用的な並行処理プログラムを構築できるようになります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?