开发者

static members when used in synchronized method or block in java

When I use a synchronized method over an instance method, the monitor is associated with 'this'. On the other hand, when I have synchronized on my class (static) method, the monitor is associated with the class object. What happens when I have a static variable used in a non-static method? Will that be synchronized?

For example,

public class A{

   public static int reg_no = 100;

   public synchronized void registration(){

   开发者_JAVA技巧   A.reg_no = some operation...

   }

}

In the above case, what will happen to the static variable reg_no if two or more threads compete for the method registration()?


When annotating a member function with synchronized, the method is synchronized on the instance of the object. If you want to synchronize on a static variable, you must manually synchronize on the class object:

public synchronized void registration() {
    synchronized (A.class) {
        A.reg_no = some operation ...
    }
}

Note that the above obtains two locks, which can lead to deadlocks if any other code obtains the same two locks in the other order. You may wish to remove synchronized from the method, leaving only synchronized (A.class).


(Revised after some further thought)

For the example presented above you can get away with declaring your static int as volatile as punkers suggested.

In the general-case however - for example if your static variable were an object with mutable state ...

The synchronized instance method means that only the thread holding the object-instance lock is allowed to progress in that method of that instance of class A, and that when the thread finishes in the method and releases the lock any other thread entering any synchronized block using the same lock will "see" the changes you made.

It does not prevent changes being made to the static variable by another thread which:

  • assigns a new value to the static variable directly from outside class A (the variable is public!)
  • calls a static method of class A (synchronized or otherwise) which reassigns the static variable, because it will use a different lock
  • calls a non-synchronized instance method of class A

Using synchronized methods is generally a bit dangerous - they can lead to deadlocks because the lock can be taken externally by other code which uses your class/instance as the target of a synchronized block:

synchronized (objectOfTypeA) { ... } // takes the instance lock

or

synchronized (A.getClass()) { ... } // takes the class lock

A better approach might be to make the static variable private, add a private local variable to use as a lock (so it cannot be locked externally), and use the private local lock in synchronized blocks in your methods:

public class A {

    private static int reg_no = 100;
    private static Object lock = new Object();

    public void registration(){
        synchronized(lock) {
            reg_no = some operation...
        }
    }

    public static int getRegNo() {
        synchronized(lock) {
            return reg_no;
        }
    }
}


Access to variables (static or instance) is not synchronized. The method's synchronization will guard against race conditions for a single instance, regardless of the variable (static or instance)

If you want to guard from multiple instances, you'd have to synchronize on the class literal, but this really looks wrong.


No, you need to synchronize the method to the class, eg. synchronized(A.class).


instead of add another syncronized block inside the syncronized method I would declare the static variable as volatile, if your problem is to share that variable with other threads.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜