Performance Tips: Java without a JIT

Synchronisation

Synchronised methods vs synchronised blocks

Lexically, there are two ways to synchronise on an object in Java. The first and arguably most common way is to declare a method as synchronized. The actual object to synchronise on is either the object on which the method is being called (non-static methods) or the Class object representing the class in which the method is defined (static methods). The second way is to write a synchronised block, explicitly stating the object on which to synchronise. So conceptually, this:

public class Foo {
  public synchronized void myMethod() {
    // Do something
  }
  public static synchronized void myStaticMethod() {
  }
}

is equivalent to this:

public class Foo {
  public void myMethod() {
    synchronized (this) {
      // Do something
    }
  }
  public static void myStaticMethod() {
    synchronized (Foo.class) {
      // Do something
    }
  }
}

In terms of what the JM does, they're not absolutely equivalent. In the first case, the instruction to synchronise is "build into" the method definition. The VM doesn't have to decode any extra bytecode instructions to do with synchronisation. In the second case, the compiled bytecode includes explicit instructions to acquire the lock at the beginning of the method and then relinquish it at the end of the method. It's only a couple of exta instructions to decode, but if the code inside the synchronised block is small, the gain might be comparably worthwhile. (Of course, in the first case, the JM does still have to do the job of acquiring then releasing the lock!)

All editorial content copyright (c) Neil Coffey 2007. All rights reserved.