Going my way

いいなと思ったことをメモしていきます。

Javaのマルチスレッドでオブジェクトをロックする方法


Advertisements


マルチスレッドアプリケーションでは、同時にアクセスされるのを防ぎ、一連の処理を保証するため、ロックをします。
同時にアクセスされることを防ぐことを同期化といいます。

あるインスタンスに関するsynchronizedメソッドは、一度に1つのスレッドしか実行できません。
synchronizedではないメソッドは、同時に2つ以上のスレッドが実行することができます。


それでは、サンプルを見てみましょう。

package thread;

public class TestThread {
	public static void main(String[] args){
		Ikemen ikemen = new Ikemen(200);
		new Thread(ikemen).start();
		new Thread(ikemen).start();
	}
}

class Ikemen implements Runnable{
	int interval=100;
	int x;
	String girlFriendName;
	
	Ikemen(int interval){
		this.interval = interval;
	}
	
	public synchronized String getGirlFriendsName(){
		x++;
		try{
			Thread.sleep(interval);
		}catch(InterruptedException e){}
		
		girlFriendName = "彼女" + x + "号";
		return girlFriendName;
	}
	
	public void run(){
		for(int i = 0; i < 5; i++){
			System.out.println(Thread.currentThread().getName() + ":" +getGirlFriendsName());
		}
	}
}

実行結果下記の通り。

Thread-1:彼女1号
Thread-0:彼女2号
Thread-1:彼女3号
Thread-0:彼女4号
Thread-1:彼女5号
Thread-0:彼女6号
Thread-1:彼女7号
Thread-0:彼女8号
Thread-1:彼女9号
Thread-0:彼女10号

getGirlFriendsName()メソッドがロックされているため、走っているスレッドから同時にアクセスされることがありません。
なので、各スレッドから同時にアクセスされて、変数に同時に加算されることを防ぐことができます。

では、synchronizedの記述をとったらどうなるでしょうか。

package thread;

public class TestThread {
	public static void main(String[] args){
		Ikemen ikemen = new Ikemen(1);
		new Thread(ikemen).start();
		new Thread(ikemen).start();
	}
}

class Ikemen implements Runnable{
	int interval=100;
	int x;
	String girlFriendName;
	
	Ikemen(int interval){
		this.interval = interval;
	}
	
	//synchronizedを外してみる
	public String getGirlFriendsName(){
		x++;
		try{
			Thread.sleep(interval);
		}catch(InterruptedException e){}
		
		girlFriendName = "彼女" + x + "号";
		return girlFriendName;
	}
	
	public void run(){
		for(int i = 0; i < 5; i++){
			System.out.println(Thread.currentThread().getName() + ":" +getGirlFriendsName());
		}
	}
}

実行結果は以下の通り。

Thread-1:彼女2号
Thread-0:彼女2号
Thread-1:彼女4号
Thread-0:彼女5号
Thread-1:彼女6号
Thread-0:彼女6号
Thread-0:彼女8号
Thread-1:彼女8号
Thread-0:彼女10号
Thread-1:彼女10号

変数に同時アクセスされて、整合性が取れなくなっていることがわかります。