💬

Goによる並列処理のお勉強(Buffering)

に公開

そろそろ、ソフトウエア工学に出戻りしないとと、最近Goをいろい始めました。まずは、以下のプログラムをみて、なぜ、デッドロックするか分かりますか?

package main
import (
	"fmt"
	"time"
)
func main() {
	const N = 3
	const capacity = N
	req := make(chan int, capacity) // リクエスト用(バッファ付き)
	start := make(chan struct{})    // サーバ開始合図(非バッファ)
	done := make(chan struct{})     // 終了通知
	// サーバ
	go func() {
		fmt.Println("[server] waiting start signal...")
		<-start // 合図が来るまで絶対に読み出しを始めない
		fmt.Println("[server] started")
		for i := 0; i < N; i++ {
			v := <-req // ここは普通に受信
			fmt.Println("[server] got request:", v)
			time.Sleep(50 * time.Millisecond) 
		}
		close(done)
	}()
	// クライアント
	go func() {
		fmt.Println("[client] sending", N, "requests...")
		for i := 0; i <= N; i++ {
			fmt.Println("[client] send:", i)
			req <- i 
		}
		fmt.Println("[client] all requests enqueued, sending start signal")
		start <- struct{}{} 
	}()
	select {
	case <-done:
		fmt.Println("[main] finished successfully")
	case <-time.After(2 * time.Second):
		fmt.Println("[main] timed out (likely deadlock)")
	}
}

あなたのプログラムは見えないバッファのおかげで辛うじて、動いているとかないですよね???

Discussion