Java and the Intrinsic Lock

I was working on converting a Java application to a multi-threaded application today and wanted to use the simplest means possible. This involves the following steps:
  1. Make the class implement Runnable or descend from the Thread class
  2. Put the previously sequential code into threads
  3. Use the "synchronized" keyword on methods that should be critical sections
  4. Join the threads before working on the results
Now, there are variations on this theme. Because each object in Java has an intrinsic lock, you can use any old Object as a mutex by calling synchronized(object){} around the critical section you want to protect.
so this:
private synchronized foo(){
  // critical section stuff
}
is the same as this:
private foo(){
  synchronized(this){
    // critical section stuff
  }
}

And when trying to synchronize multiple threads, both are wrong!!

The problem is that each object has an intrinsic lock, not each class. This is easiest to see in the second case. Because each thread is a different object, or the different thread objects contain their own instance of our Runnable class, every single lock is different. The first case has the same problem, not because the method is different in each case, but because the method is logically different.

So, what should we do?
In each case, we need to make the intrinsic lock static (or global to all instances of the class). In the first case, this can be accomplished by making the method static:
static synchronized foo(){
  // critical section stuff
}
in the second  case, we need some other object that is static to use as a lock.
static object myLock = new Object();
private foo(){
  synchronize(myLock){
    // critical section stuff
  }
}
Why would we use the second method? Probably because we want more fine grained protection over the locking than at the procedure level, or because we are referencing properties that should not be made static inside the function.

Comments

Popular posts from this blog

KnockoutJS, WebAPI, and TypeScript

The most efficient algorithm to scan a bitmap