Javaのsynchronized修飾子の対象インスタンスについての質問です。
http://www.tohoho-web.com/java/thread.htm
こちらの記事を参考にしました。
// テストプログラム class SyncTest { static Counter counter = new Counter(); public static void main(String[] args) { // スレッドを1000個作成する MyThread[] threads = new MyThread[1000]; for (int i = 0; i < 1000; i++) { threads[i] = new MyThread(); threads[i].start(); } // スレッドがすべて終了するのを待つ for (int i = 0; i < 1000; i++) { try { threads[i].join(); } catch (InterruptedException e) { System.out.println(e); } } // カウンターを表示する System.out.println(SyncTest.counter.count); } } // スレッド class MyThread extends Thread { public void run() { SyncTest.counter.countUp(); } } // カウンター class Counter { int count ; void countUp() { System.out.print("["); int n = count; // カウンターを読み出して System.out.print("."); count = n + 1; // 加算して書き戻す System.out.print("]"); } }
「この問題(スレッドの競合のことです)を防ぐには、同期処理 や 排他制御 と呼ばれる制御を行います。下記のように synchronized を用いることで、(...) で指定したオブジェクト(下記の例では this、つまり Counter オブジェクト)に対してロック権を取得した単一のスレッドのみが { ... } の処理を実行できるようになります。
(中略)
synchronized メソッドは、常にひとつのスレッドのみがそのメソッドを実行すると誤解されがちですが、スレッドを実行するインスタンスが複数あれば、インスタンスの個数だけ多重に実行される可能性がありますので注意してください。例えば、上記の例で add() ではなく run() メソッドを synchronized にしても、run() メソッドのインスタンスはスレッドの個数分 1000個ありますので、排他制御はうまく機能しません。」
つまり、例えばsynchronized(this)とすると、thisに対して、実行する権利を得たスレッドのみが{}で囲まれた部分を実行するわけですよね?
このコードで言えば、countUpメソッドにsynchronized修飾子をつけると、Counterインスタンスに対して、実行する権利を得たスレッドのみがブロックで囲まれた部分を実行することになるから、競合は起こらないという意味だと思います。
一方、私の使っている参考書(スッキリわかるJava入門編 第二版)に次のような記述がありました。
System.out.println("こんにちわ"); synchronized(this) { a +=2; } System.out.println("さようなら"); synchronized(this) { a+=3; } System.out.println("おやすみ"); synchronized(System.out) { b+=3; }
スレッドAが最後のブロック(対象インスタンスがSystem.outのブロックです)を実行している時に、真ん中のブロックを実行中のスレッドBは真ん中のブロックを実行後、この最後のブロックに入れるというような記述があります。
この本の引用ですと、「スレッドAとは対象インスタンスが違うため、侵入可。」と書いています。
System.outインスタンスが一つではないから、スレッドAもスレッドBも許可を得られるので、実行できるということなのでしょうか。
回答お願いします。
回答1件
あなたの回答
tips
プレビュー