プロが教えるわが家の防犯対策術!

JAVAを独学で勉強しております。synchronizedをインスタンスメソッドに使用したのですが、同期化できません。いくら考えてもわからなかったので、質問しました。ソースを記入します。

class Test extends Thread{

public void run(){
ss();
}
public synchronized void ss(){
for(int x=1;x<=10;x++){
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args){
Test t1 =new Test();
Test t2 =new Test();
Test t3 =new Test();
t1.start();
t2.start();
t3.start();
}
}
実行すると、同期化されてなく、ランダムに表示されます。違うオブジェクトで参照しているから、ロックかけても意味がないのかなーとも思っていますが、
Threadの拡張じゃなく、Runnableの実装に書き換えると同期化されます。なぜでしょう?自分なりに精一杯考えましたがわかりません。分かる方、説明お願いできますでしょうか?

A 回答 (5件)

とりあえずpublic synchronized void ss()をstaticにしてみてください。


詳細は参考URLをご覧ください。

参考URL:http://www.gimlay.org/~javafaq/S021.html#S021-02
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございました。
Runnableの実装の場合、なぜ同期化できるのかお分かりでしたら、教えてもらいたいのですが?
参考書を見ていると、私が書いたソースのパターンで、Runnableの実装のものが多くあります。これをThreadの拡張に変更すると、同期化しなくなります。
お分かりでしたら、おしえてください。
よろしくお願いします。

お礼日時:2004/01/13 16:54

> Runnableの実装の場合、なぜ同期化できるのかお分かりでしたら、教えてもらいたいのですが?



同期化しているのではなく、単に逐次実行しているのでは?

ご質問のプログラムでは、t1,t2,t3は異なるインスタンスなので、別個に排他制御されます。
つまり、事実上排他制御されないのです。

この回答への補足

ご回答ありがとうございます。
Runnableの実装の場合:
synchronizedキーワードがないと、t1,t2,t3、ランダムに表示されます。synchronizedを付けると、順番に表示します。
Threadの拡張の場合:
synchronizedキーワードがないと、t1,t2,t3、ランダムに表示されます。synchronizedを付けても、ランダムに表示します。

別々のオブジェクトなんで、別個に配置制御されるのは、なんとなくですが、理解できます。
Runnableの実装の場合について、もう少し詳しい情報がほしいので、お分かりでしたら、教えてください!
よろしくお願いします。

補足日時:2004/01/13 18:39
    • good
    • 0

Runnable継承版のソースコードも載せよう。



あと、for()ループの回数を10回でなくもっと長くすると、
状況が変わるような気がする。

この回答への補足

Runnableの方のソースです。

Test t1 =new Test();
Test t2 =new Test();
Test t3 =new Test();
上記のソースを下記に変更です。
Test test = new Test();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
Thread t3 = new Thread(test);
それと、Threadの拡張から、Runnableの実装に変更します。分かりにくいかもしれませんが、アドバイスお願いします!ループの件ですが、100回に変更しても結果は変わりません。よろしくお願いします。

補足日時:2004/01/13 23:10
    • good
    • 0

No.3です。


そのRunnable継承版のソースコードだと、
たしかに同期化される…。
 
 MXPXさんの書いた
 Thread継承版のソースコードと
 Runnable継承版のソースコードとでは、
 「別物の」ソースコードになっているので、
 この書き方のままでは両者を比較できない。
 (※ソースコードの書き方の違いであって、
 Thread継承とRunnable継承の違いではない)
 
 /**
  *Runnable継承版のmain()
 */
 public static void main(String[] args){
  Test test = new Test();//Testのインスタンス作成(唯一)
  Thread t1 = new Thread(test);//第1スレッド作成
  Thread t2 = new Thread(test);//第2スレッド作成
  Thread t3 = new Thread(test);//第3スレッド作成
  t1.start();//第1スレッド開始
  t2.start();//第2スレッド開始
  t3.start();//第3スレッド開始
  
  /*この時点で、3つのスレッドが存在し、
  そのいずれもが「唯一のTestインスタンスのrun()メソッド」
  を定期的に呼び出すことになる
  (つまり3つのスレッドが競って1つのインスタンスのメソッドを呼び出す)。
  いいかえると
  「スレッド3つに、呼ばれるほう1つ」。
  ってことで、その「呼ばれる」唯一のメソッドにsynchronized
  を付ければ当然、
  そのメソッド呼び出しは同期化される。
  */
 }
 
 
 /**
  Thread継承版のmain()
 */
 public static void main(String[] args){
  Test t1 = new Test();//第1Testインスタンス(かつ第1スレッド)作成
  Test t2 = new Test();//第2Testインスタンス(かつ第2スレッド)作成
  Test t3 = new Test();//第3Testインスタンス(かつ第3スレッド)作成
  t1.start();//第1スレッド開始
  t2.start();//第2スレッド開始
  t3.start();//第3スレッド開始
  
  /*この時点で、3つのスレッドが存在し、
  それぞれが「別々のTestインスタンスのrun()メソッド」
  を定期的に呼び出すことになる
  (つまり3つのスレッドが競って1つのインスタンスの
  メソッドを呼び出すわけではない)。
  いいかえると
  「スレッド3つに、呼ばれるほうも3つ」。
  呼ばれる側のメソッド1つに、
  (いわば専属の)実行用スレッド1つが対応してる感じ。
  よって同期も何もない。
  */
 }
    • good
    • 0
この回答へのお礼

試していただいてありがとうございます。
kacchannさんの説明を読ませていただくと、なるほど!と思います。ありがとうございました。

お礼日時:2004/01/14 08:40

No.1です。


現在、No.1の参考URLにアクセスできないようなので
こちらに書き込ませていただきます。

Q.メソッドに付ける synchronized って何ですか?
A.インスタンスをスレッド間で排他的に利用するための宣言です。
 排他の範囲はメソッドではなくインスタンスであることに
 注意して下さい。すなわち、 synchronized は
 「メソッドを排他的に実行するための宣言」ではありません。
 インスタンスが異なれば待たされずに同時に実行されますし、
 synchronized を付けた別のメソッドであっても
 同じインスタンスに対するものならば同時に実行されません。

ということです。
後はNo.4の方の書かれたとおりです。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!