Let Do it Let Do it - 7 months ago 27
Java Question

How really static synchronized method works in Java?

I'm trying to explore

static synchronized method
I got the theoretical concept that it's acquire lock on class, not on instance. But I'm failed to create an example where I Can test it.

Here I have created the Code to test, But both instance are accessing
static synchronized method
at the same time.

class Demo{
public static synchronized void a(){
System.out.println("A Method " + Thread.currentThread().getName());
}
}
public class StaticSyn{
public static void main(String[] args){
Demo obj = new Demo();
Demo obj2 = new Demo();

Thread one = new Thread(){
@Override
public void run(){
int i=0;
while(i<5){
obj.a();
try{
Thread.sleep(100);
}catch(InterruptedException e){

}
i++;
}
}
};
Thread two = new Thread(new Runnable(){
@Override
public void run(){
int i=0;
while(i<5){
obj2.a();
try{
Thread.sleep(100);
}catch(InterruptedException e){ }
i++;
}
}
});

one.start();
two.start();
}
}


With
static synchronized
I'm getting this output.

A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0
A Method Thread-1
A Method Thread-0
A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0


Without
static
keyword I'm getting this output.

A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0
A Method Thread-0
A Method Thread-1
A Method Thread-0
A Method Thread-1
A Method Thread-1
A Method Thread-0


So, where is the problem? and How I can test that Just one object is accessing static synchronized method.

Answer

You can add a sleep in your method a() as next:

public static synchronized void a(){
    System.out.println("Before sleep: A Method " +  Thread.currentThread().getName());
    try{
        Thread.sleep(100);
    } catch(InterruptedException e){
        Thread.currentThread().interrupt();
    }
    System.out.println("After sleep: A Method " +  Thread.currentThread().getName());
}

You will then see that you won't have 2 threads executing this block at the same time like in the next output, indeed you never have twice consecutively Before sleep:

Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1
Before sleep: A Method Thread-0
After sleep: A Method Thread-0
Before sleep: A Method Thread-1
After sleep: A Method Thread-1

What is the difference between static synchronized method and synchronized method?

The main difference is the object used to synchronize the access.

Static

For example doing this:

class Demo {
    public static synchronized void a() {
        // Rest of the method
    }
}

Is equivalent to this:

class Demo {
    public static void a() {
        synchronized (Demo.class) {
            // Rest of the method
        }
    }
}

In other words in case of a static method it uses the object representing the class itself to synchronize the access.

Non Static

For example doing this:

class Demo {
    public synchronized void a() {
        // Rest of the method
    }
}

Is equivalent to this:

class Demo {
    public void a() {
        synchronized (this) {
            // Rest of the method
        }
    }
}

In other words in case of a non static method it uses the current instance of the class to synchronize the access.