Question

I need some help to make sure that I understand synchronized blocks. Assuming the following Example:

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;
        }
    }
}
}

My Question is, is it enough to synchronize the whole queue object in ThreadA to submit an object to the queue class, to be on the safe side? I have done the same in ThreadB to delete an object from the queue. Or do i have to synchronize the submitObject() and the deleteObject() method in the Queue class, too?

In my understanding, if I lock the whole Queue class in the threads as shown above, I should be on the safe side - right?

greetZ and thanks in advance.

Was it helpful?

Solution

All you need to do here is to get sure no two threads can't get inside submitObject & deleteObjecct at the same time. To achieve that, just declare those methods synchronized. In that case, the queue object that is shared among classes will prevent 2 threads beeing on the block it synchronizes together.

If you want, moreover, to have some kind of blocking mechanism such as :

"if a thread wants to delete an object, it has to wait if there is no such an object in the queue."

then you need to do more than just synchronizing that way : both methods should be synchronized still, but a thread entering in deleteObject should be stopped using this.wait by the queue, until an object becomes available :

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

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

and then the submitObject should notify the threads in the waiting state by doing :

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

and you could also cross the roles and add some code in both methods to, for instance, allow submitter to be blocked if queue is full and notified when there is some space left in the queue.

OTHER TIPS

I would synchronize on queue object in submitObject and deleteObject methods and this should be enough, meaning that:

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

public deleteObject(int objectId){
    synchronized (theQueue) {
        ...
    }
}

What you do is equivalent to synchronizing the methods (public synchronized method() is synchronized with this which is your queue local variable) except that you have to remember that you need to do it every time you use the queue. It would be safer to synchronize the submit and delete methods.... It would also remove the Object o = new Object() from the synchronized block.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top