How can I synchronize across two different classes?

Christopher Schultz

The solution is to use a different monitor.

When you make a method synchronized, you are specifying that the currently running thread should obtain a monitor (lock) on the object which has the method. If you call another synchronized method on the same object, then everything's fine: you don't lose the lock, and other threads can't interfere.

The problem arises when you want to prevent other threads from interfering when calling methods across multiple objects. The solution is to get the VM to obtain a lock on a different object, and retain that lock until you are finished performing all of your methods, etc.

Instead of declaring a method synchronized:

public synchronized void myMethod(){
  .
  .
  .
}

Declare it non-synchronized, but use a synchronized block inside of your code:

public void myMethod(){
 synchronized(this){
   .
   .
   .
 }
}

The execution of these two methods is identical, except that the first one is a bit more efficient. However, you still haven't solved the problem, because you're still locking this. You need another object to lock. Let me set up a longer example:

public Driver{
 public static void main(String[] args){
  Test1 t1 = new Test1();
  Test2 t2 = new Test2();

  t1.doSomething();
  t2.doSomething();
 }
}

Let's say that you want to synchronize the calls to t1 and t2. It would be nice to do something like this:

synchronized(t1, t2){
  ...
}

Unfortunately, Java doesn't allow that kind of thing. Here's the part you've been waiting for:

public Driver{
 private static Object lock = new Object();

 public static void main(String[] args){
  Test1 t1 = new Test1();
  Test2 t2 = new Test2();

  synchronized(lock){
   t1.doSomething();
   t2.doSomething();
  }
 }
}

That's it! You've used an "impartial" object as the lock. You just have to make sure that other methods that want to use these methods like this are similarly synchronized, AND using the same lock object. You might want to create a singleton lock or something and always synchronize on that.

Another solution would be to create a static method in a class that was synchronized, and have that method make all the other method calls for you. It's basically the same thing as I have just explained: the "impartial" lock object is just the class that contains the static method, in this case.

Good luck,

-chris
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.