Java Synchronized Static Methods: Lock on Object or Class

Java synchronized static methods: lock on object or class

Since a static method has no associated object, will the synchronized keyword lock on the class, instead of the object?

Yes. :)

Static versus non-static lock object in synchronized block

The difference is simple: if the locked-on object is in a static field, then all instances of MyClass* will share that lock (i.e. no two objects will be able to lock on that object at the same time).

If the field is non-static, then each instance will have its own lock, so only calls of the method on the same object will lock each other.

When you use a static lock object:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), will also have to wait for thread 1 (and probably 2) to finish

When you use a non-static lock object:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), it can just continue, not minding thread 1 and 2

Which one of those you'll need depends on what kind of data you try to protect with your synchronized block.

As a rule of thumb, you want the lock-object to have the same static-ness than the operated-on value. So if you manipulate non-static values only, you'll want a non-static lock object. If you manipulate static values only, you'll want a static lock object.

When you manipulate static and non-static values, then it'll become complicated. The easy way would be to just use a static lock object, but that might increase the size of the synchronized-block more than absolutely necessary and might need to more lock contention than desired. In those cases you might need a combination of static and non-static lock objects.

In your particular case you use the lock in the constructor, which will only ever be executed once per instance, so a non-static lock-object doesn't make any sense here.

Does the lock on a static synchronized method affect the non-static synchronized methods of it's instances?

A static synchronized method will acquire the lock on the Class instance for the class. A synchronized method will acquire the lock on this. When you acquire the class level lock by calling a synchronized static method, the object-level locks are not affected.

syncronized block inside static method will acquire Class level lock or Object level lock

Every object has a "monitor". When you use a synchronized block you specify the instance whose monitor you want to synchronize on. In addition to synchronized blocks there are also synchronized methods. A synchronized instance method will acquire the monitor of the instance the method was invoked on, whereas a synchronized static method will acquire the monitor of the java.lang.Class object of the enclosing class.

public class Foo {

private static final Object STATIC_LOCK = new Object();
private final Object instanceLock = new Object();

public static void bar() {
synchronized (STATIC_LOCK) { // acquires monitor of "STATIC_LOCK" instance
// guarded code
}
}

public static synchronized void baz() { // acquires monitor of "Foo.class" instance
// guarded code
}

public void qux() {
synchronized (instanceLock) { // acquires monitor of "instanceLock" instance
// guarded code
}
}

public synchronized void quux() { // acquires monitor of "this" instance
// guarded code
}
}

If I make class level lock on static method & if one thread execute it so will it block other thread executing other instance method of same class?

the second thread will not be blocked。the class level lock & this class Object level lock,the two locks are different, but they can be re-entered each other

What is the use of static synchronized method in java?

In general, synchronized methods are used to protect access to resources that are accessed concurrently. When a resource that is being accessed concurrently belongs to each instance of your class, you use a synchronized instance method; when the resource belongs to all instances (i.e. when it is in a static variable) then you use a synchronized static method to access it.

For example, you could make a static factory method that keeps a "registry" of all objects that it has produced. A natural place for such registry would be a static collection. If your factory is used from multiple threads, you need to make the factory method synchronized (or have a synchronized block inside the method) to protect access to the shared static collection.

Note that using synchronized without a specific lock object is generally not the safest choice when you are building a library to be used in code written by others. This is because malicious code could synchronize on your object or a class to block your own methods from executing. To protect your code against this, create a private "lock" object, instance or static, and synchronize on that object instead.

Java - synchronizing static methods

Here's my test code that shows that you're right and the article is a bit over-cautious:

class Y {
static synchronized void staticSleep() {
System.out.println("Start static sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("End static sleep");
}

synchronized void instanceSleep() {
System.out.println("Start instance sleep");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println("End instance sleep");
}
}

public class X {
public static void main(String[] args) {
for (int i = 0; i < 2; ++i) {
new Thread(new Runnable() {

public void run() {
Y.staticSleep();
}
}).start();
}

for (int i = 0; i < 10; ++i) {
new Thread(new Runnable() {

public void run() {
new Y().instanceSleep();
}
}).start();
}
}
}

Prints:

Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start static sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End static sleep
Start static sleep
End static sleep

So the static synchronized has no bearing on the synchronized methods on the instances...

Of course if static synchronised methods are used throughout the system, then you can expect them to have the most impact on the throughput of a multithreaded systems, so use them at your peril...

Can we have multiple static locks in a class in java

First, this is sufficient:

private static final Object lock1 = new Object();
private static final Object lock2 = new Object();

Then, with your implementation, method1 and method2 are independent of each other, but only one instance of method1 or method2 can run among all instances of A. If you want to allow different concurrent instances of A so that method1 and method2 of different instances can run concurrently, just declare the locks without static.

In other words: if a1 and a2 are instances of A:

  • with static locks, if a1.method1 is running, a2.method1 cannot be run by another thread
  • without static, a1.method1 can be run by only one thread. a1.method1 and a2.method1 can run concurrently.


Related Topics



Leave a reply



Submit