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号
変数に同時アクセスされて、整合性が取れなくなっていることがわかります。