• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:synchronizedについて)

Javaのsynchronizedについて

このQ&Aのポイント
  • Javaのsynchronizedについて教えてください。
  • static synchronized にしていたら、排他制御が可能でしょうか?
  • sql発行メソッドを直接排他制御するのと、上記メソッドの呼出元を排他制御するのと、どちらがいいとかってあるのですか?

質問者が選んだベストアンサー

  • ベストアンサー
  • bgbg
  • ベストアンサー率53% (94/175)
回答No.3

> また、static synchronized と synchronized > どういう違いがあって、どちらを使ったらいいのでしょうか? synchronizedはそれを含むオブジェクトを排他制御の対象にします。 staticメソッドのsynchonizedは同じクラスのstaticメソッドに対して、 staticでないメソッドのsynchonizedは同じインスタンス中の他のsynchronizedに対して 排他制御がかかります。 今回のような場合はインスタンス化せず、staticで排他制御を行ったほうが良いかと思います。 サンプルコードを書きましたのでご覧ください。 staticメソッドのupdateとインスタンスメソッドのget同士では排他制御がかかりません。 さらにメソッド中でフィールド変数を使用していると、これに対しても排他制御がかかりません。注意が必要です。 public class SynchroTest1 { private static String str; public static void main( String[] args ) { for( int i = 0; i < 10; i++ ){ new SyncroTest1Thread( i ).start(); } } public static synchronized void update(String arg) { System.out.println( "-- " + arg + " start."); str = arg; try { Thread.sleep( 500 ); } catch ( InterruptedException e ) { e.printStackTrace(); } System.out.println( "-- " + arg + " finish." + str ); } public synchronized void get( String arg ) { System.out.println( "++ " + arg + " start."); str = arg; try { Thread.sleep( 500 ); } catch ( InterruptedException e ) { e.printStackTrace(); } System.out.println( "++ " + arg + " finish." + str ); } } class SyncroTest1Thread extends Thread { int id; SyncroTest1Thread ( int i ) { id = i; } public void run() { System.out.println( "Thread " + id + "in"); if( id % 2 == 0) SynchroTest1.update( "Thread " + id ); else new SynchroTest1().get( "Thread " + id ); System.out.println( "Thread " + id + "out"); } }

system0001
質問者

お礼

こんばんは。ご回答ありがとうございます! とても丁寧に説明して頂いて本当にありがとうございました☆ 説明通りでした! これから、サーブレットでも試してみます! 本当にありがとうございました☆

その他の回答 (2)

  • bgbg
  • ベストアンサー率53% (94/175)
回答No.2

分割して回答します。 > アプリケーション全体で、1ユーザがupdateしている間 > メソッドにロックをかけたいのですが、可能ですか? > > bgbgさんから頂いたサンプルをコマンドプロンプトを2つ立ち上げて、立て続けに実行したところ、 > ほぼ同時に終了したのですが、staticだからといっても、 > この場合、別々にstatic領域があると考えるのですか? コマンドプロンプト2つで実行したということは、それぞれ別のVMで起動しているということです。 VM自体が別なのでVM同士での排他制御は行われません。 通常ServletなどのWebアプリケーションは複数のリクエストでも1つのVMで動作するので、実際サーブレットを立ち上げて別々に接続してみると、きちんと排他制御されます。 サーブレットに同じ処理を書いて実験してみてください。

  • bgbg
  • ベストアンサー率53% (94/175)
回答No.1

> その場合、このメソッドを呼び出しているスレッドが終了しないうちに > 別のスレッドが呼び出した場合、そのスレッドはどうなるのでしょうか? 後から呼び出されたスレッドが待機状態になります。 前のスレッドのsynchronizedブロックが終了したら、後のスレッドが実行可能になります。 > また、sql発行メソッド(上記メソッド)を直接排他制御するのと、 > 上記メソッドの呼出元を排他制御するのと、どちらがいいとかって > あるのですか? synchronizedブロックは、そのブロックと同じオブジェクトに属する全てのsynchronizedブロックに対し排他制御をかけます。 上記メソッドの呼び出し元を排他制御しても、上記メソッド自体は排他制御されません。 つまり別のオブジェクトやメソッドから上記メソッドに自由にアクセス可能です。 SQLでの更新を制御するのが目的なら、上記メソッドに排他制御をかけるのが正しいです。 参考URLにより詳しい解説があります。ぜひご覧ください。 > 目で見て確認する方法もできれば、教えていただきたいです! 簡単なサンプルコードを。 updateとgetはともにsynchronizedブロックで、どちらかのメソッドに処理が入ると終了するまでどちらのメソッドにも処理が入れません。 public class SynchroTest1 { public static void main( String[] args ) { for( int i = 0; i < 10; i++ ){ new SyncroTest1Thread( i ).start(); } } public static synchronized void update(String arg) { System.out.println( "-- " + arg + " start."); try { Thread.sleep( 500 ); } catch ( InterruptedException e ) { e.printStackTrace(); } System.out.println( "-- " + arg + " finish."); } public static synchronized void get( String arg ) { System.out.println( "++ " + arg + " start."); try { Thread.sleep( 500 ); } catch ( InterruptedException e ) { e.printStackTrace(); } System.out.println( "++ " + arg + " finish."); } } class SyncroTest1Thread extends Thread { int id; SyncroTest1Thread ( int i ) { id = i; } public void run() { System.out.println( "Thread " + id + "in"); if( id % 2 == 0) SynchroTest1.update( "Thread " + id ); else SynchroTest1.get( "Thread " + id ); System.out.println( "Thread " + id + "out"); } }

参考URL:
http://www.javaroad.jp/java_thread4.htm
system0001
質問者

補足

こんにちは!ご回答ありがとうございました☆ サンプルソースで確認したところ、 synchronized の排他制御が理解できました。 ありがとうございました☆ まだ、初歩的なことで、疑問に残る点なのですが、 webアプリケーションでこの様な排他制御をしようと 思っているので、 アプリケーション全体で、1ユーザがupdateしている間 メソッドにロックをかけたいのですが、可能ですか? bgbgさんから頂いたサンプルをコマンドプロンプトを2つ立ち上げて、立て続けに実行したところ、 ほぼ同時に終了したのですが、staticだからといっても、 この場合、別々にstatic領域があると考えるのですか? また、static synchronized と synchronized どういう違いがあって、どちらを使ったらいいのでしょうか? wait()を使って、明示的に待機状態にした方がいいのですか? 色々と質問しておりますが、よろしくお願い致しますm(_ _)m

関連するQ&A