Потоки Java: синхронизированные блоки - PullRequest
0 голосов
/ 12 марта 2012

Мне нужна помощь, чтобы убедиться, что я понимаю синхронизированные блоки.Предполагая следующий пример:

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, чтобы удалить объект из очереди.Или мне нужно синхронизировать submitObject () и метод deleteObject () в классе Queue?

В моем понимании, если я блокирую весь класс Queue в потоках, как показано выше, я должен бытьна всякий случай - верно?

greetZ и заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 12 марта 2012

Все, что вам нужно сделать здесь, это убедиться, что никакие два потока не могут попасть внутрь submitObject и deleteObjecct одновременно.Для этого просто объявите эти методы синхронизированными.В этом случае объект очереди, который является общим для классов, не позволит двум потокам работать в блоке, который он синхронизирует вместе.

Если вы хотите, кроме того, иметь какой-то механизм блокировки, такой как:

", если поток хочет удалить объект, он должен ждать, если такого нетобъект в очереди. "

, тогда вам нужно сделать больше, чем просто синхронизировать таким образом: оба метода должны быть синхронизированы, но поток, входящий в 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

, и вы также можете пересечь роли и добавитьнекоторый код в обоих методах, например, позволяет блокировать отправителя, если очередь заполнена, и уведомлять о наличии свободного места в очереди.

1 голос
/ 12 марта 2012

То, что вы делаете, эквивалентно синхронизации методов (public synchronized method() синхронизируется с this, которая является вашей queue локальной переменной), за исключением того, что вы должны помнить, что вам нужно делать это каждый раз, когда вы используете очередь. Было бы безопаснее синхронизировать методы отправки и удаления .... Это также удалит Object o = new Object() из синхронизированного блока.

1 голос
/ 12 марта 2012

Я бы синхронизировал объект очереди в методах submitObject и deleteObject, и этого должно быть достаточно, а это означает:

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

public deleteObject(int objectId){
    synchronized (theQueue) {
        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...