Go並行処理   goroutine

ホーム   Goチュートリアル
目次


並行処理とは

並行処理(concurrent computing)は、複数の処理を同時に行うことです。並行処理と間違いやすいものに並列処理(parallel computing)があります。並列処理は一つの処理を複数の CPU で行うことです。また、コンピュータが行う処理の最小単位のことをタスク(task)と言います。

Go で並行処理を行うには、ゴールーチン(goroutine)とチャネル(channel)という方法を使います。まず、この章では、goroutine について説明します。

逐次処理

goroutine の説明の前に、普通の逐次処理についてみていきます。逐次(ちくじ)処理とは、コードの書かれた順番に一つ一つ処理が行われていくことです。順次処理、シリアル処理とも呼ばれます。特に指示をしなければ、プログラムは逐次処理で実行されます。

serial.go


package main

import (
	"fmt"
	"time"	// 時間を経過させるために time パッケージが必要です
)

func main() {

	fmt.Println("started")
	longSleep ()
	shortSleep()
	time.Sleep(time.Second * 6)	// 時間を 6 秒経過させています
	fmt.Println("main  sleep finished")
}

func longSleep() {
	time.Sleep(time.Second * 4)	// 時間を 4 秒経過させています
	fmt.Println("long  sleep finished")
}

func shortSleep() {
	time.Sleep(time.Second * 2)	// 時間を 2 秒経過させています
	fmt.Println("short sleep finished")
}
	

実行結果


started
long  sleep finished	// 4 秒経過してから表示されます
short sleep finished	// さらに 2 秒経過してから表示されます
main  sleep finished	// そしてさらに 6 秒経過してから表示されます
	

説明

main 関数が始まって、最初に longSleep 関数が呼ばれます。longSleep は 4 秒経過してから文字列を表示して処理を終えます。

次に、shortSleep 関数が呼ばれます。shortSleep は 2 秒経過してから文字列を表示して処理を終えます。

最後に main 関数でも 6 秒経過してから文字列を表示してプログラムを終了しています。

goroutine

前述の、serial.go を、goroutine を使った並行処理に変更するのは簡単です。longSleep 関数と shortSleep 関数の前に go と記述するだけです。

goroutine1.go


package main

import (
	"fmt"
	"time"
)

func main() {

	fmt.Println("started")
	go longSleep ()		// longSleep () の前に go と記述しています
	go shortSleep()		// shortSleep() の前に go と記述しています
	time.Sleep(time.Second * 6)
	fmt.Println("main  sleep finished")
}

func longSleep() {
	time.Sleep(time.Second * 4)
	fmt.Println("long  sleep finished")
}

func shortSleep() {
	time.Sleep(time.Second * 2)
	fmt.Println("short sleep finished")
}
	

実行結果


started
short sleep finished	// プログラム開始後 2 秒経過してから表示されます
long  sleep finished	// プログラム開始後 4 秒経過してから表示されます
main  sleep finished	// プログラム開始後 6 秒経過してから表示されます
	

説明

go を付けた関数は同時に処理されます。ここでは、処理時間の短い shortSleep のほうが先に処理を終えています。

main 関数の goroutine

main 関数には暗黙的に最初から go が記述された状態になっています。

main 関数のスリープ時間をなくしてみたらどうなるでしょうか。

goroutine2.go


package main

import (
	"fmt"
	"time"
)

func main() {

	fmt.Println("started")
	go longSleep ()		// computing1() の前に go と記述しています
	go shortSleep()		// computing2() の前に go と記述しています
	//time.Sleep(time.Second * 6) コメントアウトで無効化しています
	fmt.Println("main  sleep finished")
}

func longSleep() {
	time.Sleep(time.Second * 4)
	fmt.Println("long  sleep finished")
}

func shortSleep() {
	time.Sleep(time.Second * 2)
	fmt.Println("short sleep finished")
}
	

実行結果


started
main  sleep finished
	

説明

main 関数は最初から goroutine になっていますので、main 関数、longSleep 関数、shortSleep 関数が同時に処理されることになります。

main のスリープを外したために、main 関数が最初に終了します。

main 関数の終了はプログラムの終了なので、longSleep と shortSleep は処理を終えないままプログラムは終了します。

遊び

実行結果がすっきりするようにしてみました。

goroutine3.go


package main

import (
	"fmt"
	"time"
)

func main() {

	fmt.Println("started")
	go longSleep ()
	go shortSleep()
	time.Sleep(time.Second * 6)
	fmt.Println("main  sleep finished")
	time.Sleep(time.Second * 2)
	fmt.Println("finished")
}

func longSleep() {
	time.Sleep(time.Second * 4)
	fmt.Println("long  sleep finished")
}

func shortSleep() {
	time.Sleep(time.Second * 2)
	fmt.Println("short sleep finished")
}
	

実行結果


started
short sleep finished
long  sleep finished
main  sleep finished
finished
	


5313 visits
Posted: Jul. 04, 2019
Update: Jul. 04, 2019

ホーム   Goチュートリアル   目次