• 締切済み

メソッドの処理の同期化

いつもお世話になっています。 メソッド処理の同期化についてなのですが、 いろいろ調べてみたのですが、いまいちうまく実行できません。 ソースを考えてみたのですが、どこがどう悪いのかご指摘お願いできますでしょうか? 以下のクラスがある場合で public void Add(){ synchronized(this){ System.out.println("待機しています!"); //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? } System.out.println("Addメソッド実行しました"): } public void Change(){ synchronized(this) { //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? //一時停止 処理時間をずらすためループを使用 try { for(int a=0;a<3;a++){ System.out.println("a="+a); Thread.sleep(10000); } }catch (InterruptedException e) { } System.out.println("Changeメソッド完了です"); } } このとき、Add対Change/Add対Addといった形で同期化処理をしたいのですが、どうしてもうまくできません。 仮にThreadを使用して実行してみようとしたのですが、 順番に実行されてしまいます。 したいのが、 1.Addメソッド実行 2・Addメソッド実行 この場合、現状だと a=0 a=0 a=1 a=1 a=2 a=2  と表示されてしまうので、 a=0 a=1 a=2 a=0 a=1 a=2  と表示することはできるのでしょうか? 原因として、wait()/notify()が記載されていないことが影響していると思うのですが。 宜しくお願いします。

  • Java
  • 回答数2
  • ありがとう数1

みんなの回答

  • ninoue
  • ベストアンサー率52% (1288/2437)
回答No.2

Java Tutorial を参照下さい。 tutorial/essential/concurrency/guardmeth.html When wait is invoked, the thread releases the lock and suspends execution. At some future time, another thread will acquire the same lock and invoke Object.notifyAll, informing all threads waiting on that lock that something important has happened: wait, sleep, I/O wait 等でthreadの実行が中断される場合、method synchronized lockは開放され、他のthreadが同一methodの実行を始めます。 wait/sleepが解けて実行が再開される場合には、OSが介入してmethod lockを再設定します。 例えばfile read, record update, rewriteの間lockが必要な場合、method synchronized lockでは対応出来ません。 その場合、file (lock object)単位、record単位等でlockして処理する必要があります。 これらについては次に説明されているはずですので参照下さい。 tutorial/essential/concurrency/highlevel.html 

kannitiha
質問者

お礼

回答ありがとうございます。 ninoueさんの、説明してくださった点を調べてみたのですが、 どうもヒットできませんでした。 >例えばfile read, record update, rewriteの間lockが必要な場合、method synchronized lockでは対応出来ません。 >その場合、file (lock object)単位、record単位等でlockして処理する必要があります。 今度、もう一度この点を考えてみます。 後で調べたところ、 Collections.synchronizedListを使用することで無事同期化することができました。 丁寧に説明くださり、ありがとうございました。 また、質問の際には宜しくお願いします。

回答No.1

Addメソッド実行で、Changeメソッドが呼び出されているのでしょうか? それともChangeメソッドを2度実行した結果ですか?

kannitiha
質問者

補足

回答ありがとうございます。 説明ミスでした。 実行したパターンは、Changeメソッドを画面から2回実行した結果です。 試した際、多少の実行時間のずれで、 a=0 ←1回目 a=1 ←1回目  このあたりで画面から2度目のChangeメソッドが実行される a=0 ←2回目 a=2 ←1回目 a=1 ←2回目 a=2 ←2回目 といった結果になるので a=0 ←1回目 a=1 ←1回目 このあたりで画面から2度目のChangeメソッドが実行される a=2 ←1回目 2回目のChangeメソッド処理は待機中 a=0 ←2回目 a=1 ←2回目 a=2 ←2回目 としたいのですが。 また、1回目・Changeメソッド、 2回目・Addメソッドを実行し、同期化したい場合 何らかのflagをキーにして、同期化するということになるのでしょうか? 宜しくお願いします。

関連するQ&A

  • ロックの取得と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();//ここはエラーにならない } }

    • ベストアンサー
    • Java
  • synchronizedによる同期化について

    Javaで開発しています。 synchronizedで同期化したく、サンプルを作ってみたのですが上手く同期化が出来ていないようなので質問しました。 以下プログラム public class Synch{ public static void main(String[] args){ final Something obj = new Something(); new Thread(){ public void run(){ synchronized(this){ try{ obj.write(); } catch(Exception e){ }notify();} } }.start(); new Thread(){ public void run(){ try{ obj.read(); } catch(Exception e){ } } }.start(); } } class Something{ private int x = 10; private int y = 100; public synchronized void write(){ if(x < y){ System.out.println("write:x < y"); } else if(x > y){ System.out.println("write:x > y"); } for(int n = 0;n < 100;n++){ x++; y++; } for(int m = 0;m < 150;m++){ y--; } if(x < y){ System.out.println("write:x < y"); } else if(x > y){ System.out.println("write:x > y"); } } public synchronized void read(){ if(x < y){ System.out.println("read:x < y"); } else if(x > y){ System.out.println("read:x > y"); } } } このプログラムを実行すると、時々readのほうが先に表示されてしまいます。 実行環境はEclipse2.1.3です。 readが先に表示されるのは仕方のないことなのでしょうか? それともプログラムがいけないのでしょうか? ご存知の方いらっしゃいましたら教えて頂けないでしょうか。 不足がありましたら仰ってください。

    • ベストアンサー
    • Java
  • wait()したスレッドが起こされるタイミング

    以下のコードにおいて。 % java ThreadWaitTest 2 の場合はaと表示したまま止まりますが、 % java ThreadWaitTest 1 の場合はスレッドの終了に伴ってwait()が切れ、bまで表示します。 私の望む動作は前者です。 後者の場合、これはつまりスレッドをwaitした際の待機プールがスレッドオブジェクトの場合、そのスレッドの実行が終了すると待機プールにある待機スレッドを自動でnotify()してしまうことを意味していると思うのですが、この解釈はあっていますか? Java のAPIドキュメントに 「別のスレッドが notify メソッドまたは notifyAll メソッドを呼び出してこのオブジェクトのモニター上で待機するスレッドに通知を出すまで待機します」 とあるように、ユーザが明確的にnotifyしないと起こらないと思いこんでいました。 なぜこういう仕様になっているのでしょうか? また、この仕様について詳しく書いてあるサイトやドキュメントなどありませんでしょうか? public class ThreadWaitTest extends Thread {  public Object mutex = new Object();    public static void main(String[] args) {   try {    ThreadWaitTest test = new ThreadWaitTest();    test.start();    System.out.println("a");    switch (new Integer(args[0])) {    case 1:     synchronized(test) {      test.wait();     }     break;    case 2:     synchronized(test.mutex) {       test.mutex.wait();     }     break;    }    System.out.println("b");   } catch (InterruptedException ie) {    ie.printStackTrace();   }  }  public void run() {   try {    Thread.sleep(5000);   } catch (InterruptedException ie){    ie.printStackTrace();}   } }

    • ベストアンサー
    • Java
  • synchronized メソッド について

    http://www.stackasterisk.jp/tech/java/sjcp05_15.jsp ↑の問題の解答で ”あるスレッドが「9行目~11行目、15行目~19行目」までの処理を実行している間に、 「23行目~25行目」の処理を他のスレッドが実行することはありえるのです。” とあるのですが removeObj1メソッドとremoveObj2メソッドは synchronizedメソッドだと思うので removeObj1メソッドとremoveObj2メソッドが 同時に実行される事はないと思ったのですが synchronizedメソッドないにsynchronizedブロックが あるとブロック単位でのロックになるのでしょうか? addObj1が実行されているときに removeObj2が実行されるのはわかるのですが、 ”ArrayListのremove( )メソッドを呼ぶときに IndexOutOgBoundsExceptionが発生する可能性があるので 答えはC, Dになります。 と言うのがどうもわかりません。” 宜しくお願いします。

    • ベストアンサー
    • Java
  • Javaのメソッド呼び出しについて

    void usage() { System.out.println("zzz"); System.out.println("xxx"); System.out.println("ccc"); } void finish() { System.out.println("aaa"); } 上記の2つのメソッドを、mainメソッドから呼び出したいのですが どうやるのでしょうか? かなり足りない部分があるかと思うんですが、 おしえていただけないですか?

    • ベストアンサー
    • Java
  • 同期化時のことで

    いつもお世話になっています。 同期化を使用した場合のことで質問します。 private static final List<String> list = Collections.synchronizedList(new ArrayList<String>() ); を使いサーブレットでの同期化を実行しているのですが、 この場合に、値をソート化して処理を実行することは可能なのでしょうか? Collectionsを調べると、可能性としてsynchronizedSetだとできそうな気はするのですが、 その際の直列化の実装がよくわかりません。 考えているソースは以下です。 ** ラップオブジェクト同期化 **/ SortedSet sort = Collections.synchronizedSortedSet(new TreeSet<String>() ); /** サーブレットクラスでの処理 **/ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //リクエストデータ String key = request.getParameter("key"); //リクエストデータをSortedSetに格納する sort.add(key); //←この時点で、直列化のための何らかの処理がいる try{ //実行時、時間をずらすために宣言 Thread.sleep(1000); }catch(Exception e){ } //何の処理もしなかったら、実行された画面の順で処理が開始される synchronized(sort){ for(int a=0;a<10;a++){ System.out.println("a="+a); } } //SortedSetに格納された値の順 List sortList = new ArrayList(sort); for(int s=0;s<sortList.size();s++ ){ //↓すべての処理が終わってみたら、確かにソート化されているs System.out.println("sortList["+s+"]="+sortList.get(s)); } } jsp側のリクエストデータ 1回目 C 2回目 B 3回目 A 実行させたい順 C→A→B このとき、B,Aが渡されるタイミングは、Cの処理が実行中時 また、どのキーに対しての実行中なのかを見ることはできるのでしょうか? Collectionsクラスを見たところなさそうだったのですが。。。 宜しくお願いします。

    • ベストアンサー
    • Java
  • メソッドのオーバーライド(java)

    class A3{ void hello(){ System.out.println("A3"); } void hello(int i){ System.out.println("A3"+i); } } class B3 extends A3{ void hello(){ System.out.println("B3"); } } class C3 extends B3{ void hello(String s){ System.out.println("C3"+s); } } class MethodOverriding3{ public static void main(String args[]){ A3 obj = new C3(); obj.hello(); } } 上のプログラムを実行すると"B3"と表示されまが、どうしてクラスBのメソッドが実行されるのでしょうか? クラスAのメソッドが無視される仕組みがわかりません。 また、クラスMethodOverriding3でobj.hello("abc")としてコンパイルすると mo.java:25: シンボルを見つけられません。 シンボル: メソッド hello(java.lang.String) 場所 : A3 の クラス obj.hello("abc");   ^ エラー 1 個 とエラーが出ます。 どうしてでしょうか? 誰か教えてください、お願いします。

    • ベストアンサー
    • Java
  • Javaでメソッドの引数にメソッド

    以下のようにメソッドの引数にメソッドを渡したいです。 static void methodA(methodB, str) { methodB(str); } static void methodB(str) { System.out.println(str); } つまりメソッドAにメソッド名「methodB」と文字列「str」を渡して、間接的にメソッドBを実行させたいということです。 getMethodやinvokeを使うのかなとは思ったのですが、よく理解できませんでした。 上記のようなことは可能でしょうか?

    • ベストアンサー
    • Java
  • 実行中のメソッド名

    お世話になります。 実行中のメソッド名を取得することってできますか? public void methodA(){ System.out.println(□□□+"というメソッドが呼ばれました"); } の□□□になにをいれたらよいでしょうか? クラス名は取れる(this.class.getClass().getName())のですが実行中のメソッドってとれないのでしょうか? 以上よろしくお願い致します。

    • ベストアンサー
    • Java
  • スレッド1とスレッド2を交互に実行するには?

    スレッド1→スレッド2→スレッド1・・・と同期を取り合いながら交互にスレッドを動かしたいのですが、Thread.getState()を用いないで実現するよい方法はないでしょうか? どうしてもデッドロックが発生しうる方法しか思いつかず困っています。 例えば以下のプログラムで1212と交互に表示させたい場合です。 以下のプログラムは当然デッドロックになりますが、やりたいことを伝えるために載せておきます。 Object obj; //スレッド間通信用のobject class Test1 extends Thread {  public void run() {   while(true) {    System.out.print("1");    synchronized (obj) {     obj.notify();//相手をnotifyして     obj.wait();//自分はwait    }   }  } } class Test2 extends Thread {  public void run() {   while(true) {    System.out.print("2");    synchronized (obj) {     obj.notify();     obj.wait();    }   }  } } new Test1().start(); new Test2().start();

    • ベストアンサー
    • Java

専門家に質問してみよう