Stephan
Stephan

Reputation: 17971

Synchronization across classes

I have two threads running concurrently, a main thread and a listener that implements Runnable.

The main thread and listener each have a critical section, specifically the method getObjectList(String) in the Manager class that runs in the main thread and handleNewObjects(String, List<Object>) that runs in the listener thread.

My current plan is to make getObjectList() a synchronized method:

class Manager {

    protected synchronized getObjectList() {
        // Do critical section stuff
    }
}

and make handleNewObjects() look like this

class Listener implements Runnable {
    private final Manager myManager;

    handleNewObjects() {
        synchronized (myManager) {
            // Do critical section stuff
        }
    }
}

Will this ensure my critical sections never run simultaneously?
Should I synchronize some other way?

Upvotes: 2

Views: 178

Answers (3)

NESPowerGlove
NESPowerGlove

Reputation: 5496

If getObjectList() was to be a synchronized method, and myManager in Listener was the same Manager instance as the instance that will modify a shared set of objects, then yes it would work.

It is hard to say without knowing the relationships between your existing code to know if there's a better solution for you, however this approach could be seen as somewhat fragile. A change to what object Manager locks on would cause Listener to not be thread-safe anymore, and if the shared objects the two critical sections modify already exist in Manager, you might as well have Listener call another synchronized in Manager, say myManager.handleNewObjects().

What I mean by a change to what object Manager locks on is if Manager went from:

protected synchronized getObjectList() {
    // Do critical section stuff
}

to

protected getObjectList() {
    synchronized (myPrivateFinalLockObject) {
        // Do critical section stuff
    }
}

or

protected getObjectList() {
    delegatingWorkToSomeOtherThreadSafeObject.getObjectList();
}

Then Listener isn't thread-safe anymore as it doesn't lock it's critical section on the same object anymore.

Upvotes: 1

Khanna111
Khanna111

Reputation: 3913

Assuming that getObjectsList is a retrieval method with no updates, you could improve on concurrency utilizing ReadWriteLocks. Here the handle* method is the method that updates the underlying list. Please see: http://ilkinbalkanay.blogspot.com/2008/01/readwritelock-example-in-java.html

Upvotes: 0

John R
John R

Reputation: 2096

Will this ensure my critical sections never run simultaneously?

Yes, but as Quirliom noted, be sure they are the same object. If you're using any frameworks, beware of framework created proxies.

Should I synchronize some other way?

Producer-consumer setups are pretty common. Things get trickier when you have multiples of each. Rather than reinvent it yourself, you can take a look at some classes that are built into the platform. From the Javadocs (not exactly what you're doing, but close):

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

Upvotes: 1

Related Questions