2012-03-28 3 views
1

モニターオブジェクト?Javaは、私がいることを読ん

私のコードでこれを試しても動作しません。

private Object data; 
    private Object sync = new Object(); 

    public static void main(String[] args) { 
     SimpleProducerConsumer pc = new SimpleProducerConsumer(); 
     new Thread(pc.new Producer()).start(); 
     new Thread(pc.new Consumer()).start(); 
    } 

    public Object pop() { 
     try { 
      sync.wait(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     System.out.println("Before"); 
     Object d = data; 
     data = null; 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("pop"); 
     System.out.println("After"); 
     sync.notify(); 
     return d; 
    } 

    public void push(Object d) { 
     try { 
      sync.wait(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     try { 
      Thread.sleep(10); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     data = d; 
     System.out.println("push"); 
     sync.notify(); 
    } 

    class Producer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       push(new Object()); 
      } 
     } 
    } 

    class Consumer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       pop(); 
      } 
     } 
    } 

私のコードに問題がありますか?

答えて

3

いいえ、sync.wait()およびsync.notify()は、sychronize (sync) { ...および... }と同義語とは限りません。

実際には、waitを呼び出すために、あなたは​​ブロックにするを持っている

synchronize,waitおよびnotifyの概念について説明しますが、その違いは明らかです。スレッドは、それが(ロックが取られていることと、他のスレッドがその時点でブロックに入ることができないことを意味する)syncモニタのロックをグラブsynchronized (sync) { ... }ブロックに入る

  • スレッドがsync.wait()を呼び出すと、ロックは一時的にsyncのロックを解除します。 (これはが起こることを何かのためを待っているのです。起こることができるようにロックが必要な何か。)

  • スレッドがsync.notify()には、その時点では、実行を再開が起こった何か、他のスレッドに通知呼び出します。

は私のコードの何が問題になっているのですか?私は、インスタンスのためにあなたを想定し

は、2つのスレッドが何かをポップしようとした場合、彼らがやって避けるべきであることを確認するには、次の

Thread 1    Thread 2 
-------------------------------------- 
Object d = data; 
         Object d = data; 
         data = null; 
data = null; 
return d; 
         return d; 

あなたは必ずd = datadata = nullことを確認する必要があり、これを避けるにはが原子的に発生します。

この

Object d; 
synchronized (sync) { 
    d = data; 
    data = null; 
} 

を行うことによって達成することができる(今上のスレッド1における第1および第2の文を分割することはできません。)

さらにあなたはpopがブロックされるようにしたいように見えます、つまり、d == nullの場合は、他のスレッドがpushになるのを待つ必要があります。

これは

synchronized (sync) { 
    while (d == null) 
     sync.wait(); 
} 

を行うことによって達成することができ、(プッシュ方式でアトミックに行われる必要があり、すべてを網羅​​ブロック以内に再度)pushsync.notify()を行います。

関連質問/さらに読書:

1

あなたがnotify()に同じロック・オブジェクトで待機しているの両方ごpush()pop()方法がありますが、そのオブジェクトのnotify()またはnotifyAll()を呼び出し、誰もありませんので、彼らはいつまでも待っています。ここでは何が起こる は次のとおりです。

  1. push()内側sync.wait()コールのプロデューサーが待機を誰かがコールするために、誰かがpop()sync.wait()コールにsync.notify()
  2. 消費者が待機を呼び出すためsync.notify()
  3. デッドロック
1

いいえ、それらはまったく異なります。何らかの条件が満たされるまで実行を中断したい場合はwait()を​​ブロックの内側から呼び出します。同一のオブジェクトにnotify()またはnotifyAll()を使用します(同じく​​ブロック内)。

したがって、この状況では、2つのスレッドが実際に同時に同じオブジェクトに​​ブロックであってもよいです。そのうちの1人がwait()を行ったときに許可されます。 2番目のスレッドがを呼び出したブロック​​を終了すると、最初のスレッドが再び起動します。

関連する問題