• ベストアンサー

ロックの取得とwaitメソッド

インスタンスに対してwait()メソッドを実行するには、そのインスタンスのロックを取得していなくてはならないと思っています。 method2()がエラーになるのと、method3が正常に動作するのは、 インスタンスに対するロックの有無で理解できます。 ただ、下記のソースでmethod()がエラーとならない動作が理解でき ませんでした。 このメソッドだと、メソッド単位ではロックがかかっていますが、 synchronizedでないメソッドが存在すれば別スレッドからアクセスでき るので、インスタンスに対するロックを取得しているわけではないと思 います。 私の理解が間違っているのでしょうか。 class MyClass { String str = new String("a"); public synchronized void method(){ try{ wait(); } catch (Exception e) { e.printStackTrace(); } } public void method2(){ synchronized (str) { try{ wait(); }catch(Exception e){ e.printStackTrace(); } } } public void method3(){ synchronized (this) { try{ wait(); }catch(Exception e){ e.printStackTrace(); } } } } class UseMyThread1 { public static void main(String args[]) { MyClass mc1 = new MyClass(); MyClass mc2 = new MyClass(); MyClass mc3 = new MyClass(); //mc1.method();//ここはエラーにならない System.out.println("*********"); //mc2.method2(); //ここはエラーになる System.out.println("*********"); //mc3.method3();//ここはエラーにならない } }

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

  • ベストアンサー
  • ngsvx
  • ベストアンサー率49% (157/315)
回答No.3

#1です。 もしかしたら、method3に対する理解も間違っているかもしれないので、もう少し詳しく説明します。 まず、synchronized(x)というのは、xのモニターを取得することを意味します。 モニターというのは、1つのオブジェクトに対し1つのスレッドしか取得できません。 モニターを取得しようとしたときに、他のスレッドが既にそのオブジェクトのモニターを取得していた場合は、モニターが取得できるまで待機させられます。 また、synchronizedメソッドというのは、そのメソッドを持つオブジェクトのモニターを取得することを意味します。 つまり、synchrozied(this)と同じだということです。 一方synchronizedとは関係ないメソッド等は「モニターの取得」の動作を行いません。 スレッドの待機が起こるのは、モニターを取得するときなので、他のスレッドがモニターを取得していても、synchronizedではないメソッドは実行できることになります。 なお、「モニター」というのはJAVAでの正式用語です。 わからない箇所があれば補足して下さい

その他の回答 (2)

  • dyna_1550
  • ベストアンサー率34% (122/353)
回答No.2

#1の方が仰られているとおり、method()とmethod3()は同じです。 synchronizedメソッドを利用した場合、thisオブジェクトがモニタになります。 method2()では、this.wait(0)を呼んでいますが、このオブジェクトのモニターを所有するスレッドとなっていないため エラーとなります。

参考URL:
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/api/java/lang/Object.html#wait()
  • ngsvx
  • ベストアンサー率49% (157/315)
回答No.1

この場合のmethod()とmethod3()は、ほぼ同じことです。 実質的には全く同じと思っていいと思います。

solarin
質問者

お礼

回答ありがとうございます。 waitメソッドを実行するにあたってはmethod()とmethod3()は同じ動作をすることはわかりました。ただやはり気になるのは、MyClassのインスタンスを作ってmethod()を実行した場合、他のスレッドからsynchronizedでないメソッドにはアクセスができると思いますが、それでもインスタンスに対するロックを取得したことになるのでしょうか。