マルチスレッド2

はじめに

前回のエントリでは,マルチスレッドとは何か,スレッドの起動方法について述べた.本エントリでは,スレッドの排他制御および協調について述べる.

スレッドの排他制御

排他制御」とは,一度に複数のスレッドが同じ処理をしないことをいう.
複数のスレッド thread1, thread2が走っていて,ある処理を実行しようとしているとする.thread1 がある処理をしている間,thread2はその処理を行わず,thread1の処理が終わるのを待つ(終わり次第,その処理を行う).このような振る舞いを,スレッドの排他制御という.

排他制御には,synchronizedキーワードを使う.
synchronizedキーワードをつけたメソッドを,synchronizedメソッドという.書き方としてはこんな↓感じ.

public synchronized void output() {
    System.out.println("Hello, world!");
}

synchronizedメソッドは,一度に1つのスレッドしか実行できない.
つまり,thread1がoutputメソッドを実行している間,thread2はoutputメソッドを実行することができない.
※synchronizedキーワードをつけていないメソッドは,一度に複数のスレッドを実行できる.

ちなみに,あるスレッドがsynchronizedメソッドを実行しているとき,そのスレッドはロックをとっている(acquire)状態であるという.あるスレッドがロックをとっている間,ほかのスレッドはそのメソッドを実行できない.
また,synchronizedメソッドを実行していたスレッドが処理を終えると,ロックが解放(release)され,この時点で,待ちぼうけを食らっていたほかのスレッドがロックをとることができるようになる.

スレッドの協調

synchronizedメソッドに関連して,スレッドが実行できるようになるまで「待つ」,実行できるようになったら,そうなったと「知らせる」ためのメソッドJavaには用意されている.
メソッドの説明に入る前に,必要な用語について述べる.

【wait set】
・スレッドがロックをとれなかったときに,スレッドが一時的にストアされる場所.
 →訳あって家に入れないとき,とりあえず満喫かどこか行きますよね(行くかな?).
  その満喫という「場所」がwait setというイメージ.

wait setの意味を踏まえたうえで,先述のメソッドについて記載する.

【waitメソッド】
・ロックをとれなかったとき,wait setに現在のスレッドをストアする命令.
 →「家に入れないか.よし,満喫行こうぜ!」
【notifyメソッド】
・wait setの中で控えているスレッドを起動する命令.
 →「よし,もう家に来ていいぞ.カモン!」
【notifyAllメソッド】
・wait setの中に控えているすべてのスレッドを起動する命令.
 →「お前らみんなまとめて俺ン家来いよ!」

おわりに

マルチスレッドに関する事柄,特にスレッドの排他制御・協調について述べた.

・スレッドの排他制御
  - synchronizedキーワード
・スレッドの協調
  - wait set,waitメソッド,notifyメソッド,notifyAllメソッド

どちらかというと言葉での記載がメインになったので,読みにくいところもあったと思う.実際に図にしてみたらイメージもつかみやすいと思うが,気が乗らなかったので言葉での説明にウェイトを置いた形になった.知識を整理するという意味でも,気が向けば図解してみようかな・・・?