0

同期されたブロックを確実に理解するために、いくつかの助けが必要です。次の例を想定します。

public class ThreadStarter {
    public static void main(String[] args) {

        Queue queueObject = new Queue();

        ThreadA thread1 = new ThreadA(queueObject);
        ThreadA thread2 = new ThreadA(queueObject);

        ThreadB thread3 = new ThreadB(queueObject);
        ThreadB thread4 = new ThreadB(queueObject);

        thread1.start();
        thread2.start();

    }
}

public class Queue {

    Object[] the theQueue;

    public Queue(int size){
        theQueue = new Object[size];
    }

    public submitObject(Object o){
        /* add Object to the queue */
    }

    public deleteObject(int objectId){
        /*delete Object from the queue */
    }
}

public class ThreadA extends Thread {

    private Queue queue;

    public ThreadA(Queue queue){
        this.queue = queue;
    }

    public void run() {
        while(!isInterrupted()){
            synchronized(queue) {
                Object o = new Object
                queue.submitObject(o);
                 /* do some other stuff */
        }

        try {
            sleep((int)(Math.random()*1000));
        } catch (interruptedException) {
            Thread.currentThread().interrupt;
        }

            synchronized(queue) {
                 /* do some other stuff on the queue */
            }
        }
    }
}

public class ThreadB extends Thread {

    private Queue queue;

    public ThreadB(Queue queue){
        this.queue = queue;
    }

    public void run() {
        while(!isInterrupted()){
            synchronized(queue) {
                queue.deleteObject(o);
                /* do some other stuff */
        }

        try {
            sleep(1000);
        } catch (interruptedException) {
            Thread.currentThread().interrupt;
        }
    }
}
}

私の質問は、安全のために、ThreadAのキューオブジェクト全体を同期してオブジェクトをキュークラスに送信するだけで十分ですか?ThreadBでも同じことを行って、キューからオブジェクトを削除しました。または、QueueクラスのsubmitObject()メソッドとdeleteObject()メソッドも同期する必要がありますか?

私の理解では、上記のようにQueueクラス全体をスレッドにロックすると、安全な側にいるはずです-そうですか?

greetZと事前に感謝します。

4

3 に答える 3

2

ここで行う必要があるのは、2 つのスレッドが submitObject と deleteObject の内部に同時に入ることができないようにすることだけです。これを実現するには、これらのメソッドを同期することを宣言するだけです。その場合、クラス間で共有されるキュー オブジェクトは、一緒に同期するブロックで 2 つのスレッドが存在するのを防ぎます。

さらに、次のようなある種のブロックメカニズムが必要な場合:

「スレッドがオブジェクトを削除したい場合、キューにそのようなオブジェクトがない場合は待機する必要があります。」

次に、そのように同期するだけではありません。両方のメソッドを同期する必要がありますが、deleteObject に入るスレッドは、オブジェクトが使用可能になるまで、キューによって this.wait を使用して停止する必要があります。

public synchronized deleteObject() {
  while( isEmpty() ) {
    try {
      wait();
    } catch( Exception ex ) {
      ex.printStackTrace();
    }//catch
  }//while

  //actually do delete object.
  ...
}//met

次に、submitObject は次のようにして、待機状態のスレッドに通知する必要があります。

public synchronized submitObject() {
  //do put object
  ...
  notifyAll();
}//met

また、役割を超えて両方のメソッドにコードを追加して、たとえば、キュ​​ーがいっぱいの場合にサブミッターをブロックし、キューにスペースが残っている場合に通知できるようにすることもできます。

于 2012-03-12T19:48:15.590 に答える
1

キュー オブジェクトsubmitObjectdeleteObjectメソッドで同期しますが、これで十分です。つまり、次のようになります。

public submitObject(Object o){
    synchronized (theQueue) {
        ...
    }
}

public deleteObject(int objectId){
    synchronized (theQueue) {
        ...
    }
}
于 2012-03-12T19:40:21.687 に答える
1

あなたがすることは、メソッドを同期することと同じです (public synchronized method()はローカル変数と同期されthisますqueue)。ただし、キューを使用するたびにそれを行う必要があることを覚えておく必要があります。submit メソッドと delete メソッドを同期する方が安全です.... またObject o = new Object()、同期ブロックから を削除します。

于 2012-03-12T19:40:43.547 に答える