スレッドの同期を取るもう一つの手段として
shnchronizedブロック があります。
以下のように記述することにより()内で指定したオブジェクトのモニタを獲得することができます。
synchronized(obj){
//ステートメント
}
{}内ではobjのモニタを獲得していますが、{}を抜けるとモニタを開放します。
以下にsynchronizedブロックを使用した例を示します。
以下のクラスのaddIメソッドを実行すると、まずobj1のモニタを獲得し、変数iをインクリメントして1秒待機しています。
待機後、addIメソッドを実行したスレッド名とiを表示して終了しています。
public class MySynchronized {
Object obj1;
int i;
MySynchronized(){
obj1 = new Object();
i = 0;
}
public void addI(String name){
synchronized (obj1) {
i = i + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(name + ":" + getI());
}
}
public int getI(){
return i;
}
}
以下は、上記クラスをインスタンス化し、二つのスレッドでaddIを呼んでいます。
addIメソッド内でsynchronizedしているため、addIは交互にモニタを獲得し、同期が取れているのがわかります。
public class TEST {
static MySynchronized ms = new MySynchronized();
public static void main(String[] args){
Thread thread1 = new Thread(){
public void run(){
for (int i=0;i<5;i++){
ms.addI("thread-1.add");
}
}
};
Thread thread2 = new Thread(){
public void run(){
for (int i=0;i<5;i++){
ms.addI("thread-2.add");
}
}
};
thread1.start();
thread2.start();
}
}
上記、Javaアプリケーションを実行すると結果は以下のようになります。
最初にthread-1がaddIメソッドを実行し、その中で1秒待機しているため、thread-2がモニタ獲得待ち状態になり、thread-1がモニタ解放後thread-2がaddIを実行しているのがわかります。
そのモニタ獲得と開放を繰り返しthread-1とthread-2の間で繰り返しています。
thread-1.add:1
thread-2.add:2
thread-1.add:3
thread-2.add:4
thread-1.add:5
thread-2.add:6
thread-1.add:7
thread-2.add:8
thread-1.add:9
thread-2.add:10