Synchronization: Object vs Class level

In my last post I wrote about how synchronization can help making sure that multiple threads do not execute same block of code at the same time. I will take the concept of synchronization a little further here. Going back to previous example.

public void test()
{
 synchronized(this){
  try {
   count++;
   Thread.sleep(1000);
   System.out.println(“Hello from Runnable:”+count);
   } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

synchronized(this) or using synchronized keyword at method level makes sure that no 2 threads execute the block of code at the same time. But there is a bit more to it. To elaborate, I have modified my test method slightly

public void test()
{
 synchronized(this){
  try {
   count++;
   Thread.sleep(1000);
   System.out.println(Thread.currentThread().getName()+" says Hello from  R unnable:"+count); 
   } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

And modified calling main method

public static void main(String s[])
{
Runnable r=new RunnableTest();
Runnable r2=new RunnableTest();
for(int i=0;i<20;i++)
{
Thread t1=new Thread(r);
t1.setName("1");
t1.start();
Thread t2=new Thread(r2);
  t2.start();
  t2.setName("2");
 }
}

Now if I run this we will see something like

2 says Hello from Runnable:1
1 says Hello from Runnable:1
1 says Hello from Runnable:2
2 says Hello from Runnable:2
1 says Hello from Runnable:3
2 says Hello from Runnable:3

And if you will observe the output, it is appearing in pairs. So let us understand what is happening here.

First change, instead of one object of runnable we are using 2 objects, this is to basically highlight the behavior in synchronized(this) block. Second change is that I added name for thread so that we can print it out to understand which thread is actually executing.

Coming back to synchronized(this), look at the “this” keyword. “this” in Java refers to current object. So when we synchronize on this, it means we are synchronizing on current object, so as we are using two different objects, hence we see the behavior that two stream of threads is executing simultaneously in synchronized block. So we can say that with synchronized this, we make sure only one thread of the object is executing in synchronized block at a time.

Now there can be a situation where you want exactly one thread for whole class gets executed at a time, no matter if thread belongs to same object or not. There is a simple solution to it.

public void test()
{
 synchronized(RunnableTest.class){ //Change this with class name
  try {
   count++;
   Thread.sleep(1000);
   System.out.println(Thread.currentThread().getName()+" says Hello from  Runnable:"+count);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

There are other options for synchronization as well, not of much practical use (atleast I have not used them ever), but worth noting.

synchronized("1")

Remember, string is an object. So we are synchronizing based on a constant object here, which will make sure only one thread executes at a time, irrespective of class or objects. So for our example this will be same as synchronized(RunnableTest.class).

A more practical use can when we are trying to synchronizing a group of thread.

String key=Thread.currentThread().getName();
public void test()
{
 synchronized(key){
  try {
   count++;
   Thread.sleep(1000);
   System.out.println(Thread.currentThread().getName()+" says Hello from Runnable:"+count);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

Here I am using key to group threads based on which synchronization is done. The key here is simply name of thread, but it can be more realistic in real scenario.