Monday, July 21, 2008

Concurrent execution of static and non-static synchronized methods


Concurrent execution of static and non-static synchronized methods


We have a scenario where we have a static synchronized method and a non-static synchronized method. As we know that a static method can only access static members of the class whereas a non-static method can access both static as well as non-static members. This liberty can put us into a situation where a non-static method might be updating some static data which a static method would also be changing. What will happen if two different threads try to access the static and non-static synchronized methods concurrently and in turn try to change the static data using the two methods? Will the synchronization guarantee mutual exclusion in such a case?


No... synchronization won't guarantee mutual exclusion in such a case as both the threads may access the static and non-static synchronized methods concurrently because a non-static synchronized method requires the invoking thread to acquire a lock of the particular object on which the thread invokes the non-static synchronized method whereas a static synchronized method will require the invoking thread to acquire a lock on the java.lang.Class object associated with the particular class (which the static method is a part of). Both these locks have nothing to do with each other and they can be acquired by different threads at the same time and hence two different threads may execute a static method and a non-static synchronized method of a class respectively at the same time (of course once they acquire the two locks).


It is certainly not advisable to allow such a thing to happen and hence the design of such a class needs to be re-checked. Otherwise the errors caused by simultaneaous modification of the same static data by different threads may infuse some really-hard-to-detect bugs.


Thus, we see that only declaring the methods as synchronized doesn't ensure mutual exclusion and the programmer should always think about the locks involved to achieve the actual purpose of synchronization.


Have a look at the following simple example where the same static data is being modified by two public synchronized methods - one being static and the other being non-static. The whole purpose of synchronization is getting defeated here as in such a case mutual exclusion can't be guaranteed, which is one of main purposes of using synchronization.


public final class BadDesign{

private static int sensitiveData;

public synchronized static void changeDataViaStaticMethod(int a){

//... updating the sensitiveData

sensitiveData = a;

}


public synchronized void changeDataViaNonStaticMethod(int b){

//... updating the sensitiveData

sensitiveData = b;

}


public static void showSensitiveDataStatic(){

System.out.println("Static: " + Thread.currentThread().getName()+ " - " + sensitiveData);

}


public void showSensitiveData(){

System.out.println(Thread.currentThread().getName() + " - " + sensitiveData);

}


public static void main(String[] args){

new Thread(new TestThread11()).start();

new Thread(new TestThread11()).start();

}


}


class TestThread11 implements Runnable{


public void run(){

int i = 0;

do{

BadDesign.changeDataViaStaticMethod(5);

BadDesign.showSensitiveDataStatic();


//... new object for every iteration

//... so synchronization of non-static method

//... doesn't really do anything significant here

BadDesign bd = new BadDesign();

bd.changeDataViaNonStaticMethod(10);

bd.showSensitiveData();

}while (i++ < 100);

}

}


An excerpt from the output:-

...

Static: Thread-0 - 5

Thread-0 - 10

Static: Thread-0 - 5

Thread-0 - 10

Thread-1 - 10

Static: Thread-0 - 5

Static: Thread-1 - 5

Thread-1 - 10

...


By looking at the above exceprt you can easily conclude that the static and non-static synchronized method calls are intermixed between the two threads: Thread-0 and Thread-1. In this case the non-static synchronized method is always being called on a new object (as the do-while loop of the run() method is creating a new object of the class BadDesign for every non-static synchronized method call) by both the threads and hence synchronization doesn't really do anything significant for them as every new object will have its own lock which will be easily acquired by the invoking thread everytime the do-while loop iterates. I've kept this just to make the code simple as my purpose of the above example is just to show that static synchronized methods and non-static synchronized methods are completely independent of each other and both of them can run at the same time by different threads for the simple reason that both these methods are governed by different locks which may be acquired at the same time by two different threads.


Liked the article? You may like to Subscribe to this blog for regular updates. You may also like to follow the blog to manage the bookmark easily and to tell the world that you enjoy GeekExplains. You can find the 'Followers' widget in the rightmost sidebar.



Share/Save/Bookmark


3 comments:

Anonymous said...

superb explanation, i was looking for solution of that problem

arun gangawat Gangawat said...

I found best java related articals here..

arun gangawat Gangawat said...

I found best java artical here...very good