Goスレッドプログラミング入門
前提条件
- スレッドとは何かを知っている
- スレッドプログラミングある程度経験済み
スレッド実行
java
スレッド処理実行クラスを使う。
スレッドで実行する処理はそれぞれ実装する。
Threadクラスを継承したクラスを作成して実行する。
Web開発のためのJava入門 10章:スレッド : 富士通アプリケーションズ
class ProcA implements Runnable {
public void methodA() {
}
public void run() {
// 実行したい処理
methodA()
}
}
class ProcB implements Runnable {
public void methodB() {
}
public void run() {
// 実行したい処理
methodB()
}
}
// 実行
Thread threadA = new Thread(new ProcA());
threadA.start();
Thread threadB = new Thread(new ProcB());
threadB.start();
Go
キーワードgoを使って関数呼び出しするとスレッドが作成される。
Go言語の場合、スレッド(クラスに相当するモノ)をGoroutineと呼ぶ。
プログラム処理(main)もGoroutine上で動作する。メインGoroutineと呼ぶ。
これはJavaも同じ。
func funcA() {
}
func main() {
go funcA();
}
スレッド間のメソッド呼び出し
Java
クラスのメソッドは何の制限もなく呼び出すことができる。
ただし、複数スレッドから非同期にリソース更新させたくない場合にはsynchronizedキーワードを追加する。
これにより単一スレッドからのアクセスに制限できる。
public synchronized void methodB() {
}
##Go
メソッド呼び出しはchannelを使って行う。
goのchannelは、スレッド機能(goroutine)と送受信データ管理機能を持つ。
これにより、スレッド(goroutine)間のメッセージを送受信(Message Passing)を実現している。
以下の例は、メインgoroutineから別goriutine(新しいchannelを実行する)にメッセージ送信している。
Go by Example: Channels
func main() {
// Create a new channel with `make(chan val-type)`.
// Channels are typed by the values they convey.
messages := make(chan string)
// _Send_ a value into a channel using the `channel <-`
// syntax. Here we send `"ping"` to the `messages`
// channel we made above, from a new goroutine.
go func() { messages <- "ping" }()
// The `<-channel` syntax _receives_ a value from the
// channel. Here we'll receive the `"ping"` message
// we sent above and print it out.
msg := <-messages
fmt.Println(msg)
}
channelについて
作成
受信するデータの型を指定して作成する。
messages := make(chan string)
送信
<-キーワードを使ってデータを送信する。
送信元スレッド(処理を実行しているgoroutine)
送信先スレッド(channelが動作しているgoroutine)
messages <- "ping"
受信
<-キーワードを使ってデータを受信する
受信元スレッド(channelが動作しているgoroutine)
受信先スレッド(処理を実行しているgoroutine)
msg := <-messages
##buffering(複数データ受信)
デフォルトではchannelは単一データのみを受信(保持)する。複数データ受信したい場合には、channel作成関数に引数(個数)を追加する。
文字列型のデータを2つ保持するchannelを作成する。
messages := make(chan string, 2)
messages := make(chan string, 2)
##Channel Synchronization
単一データ受信channelからデータを受信する場合、データ受信するまで受信先スレッドがロックされる。
データ受信していない場合、プログラム(メインgoroutine)の終了とともにすべてのgoroutineが終了する。
Channel Synchronization
func worker(done chan bool) {
//...
// Send a value to notify that we're done.
done <- true
}
func main() {
// Start a worker goroutine, giving it the channel to notify on.
done := make(chan bool, 1)
go worker(done)
// Block until we receive a notification from the worker on the channel.
<-done
}
複数goroutineの終了を待つ場合には、WaitGroupsを使うことができる。
Go by Example: WaitGroups