Search code examples
javamultithreadingstaticsynchronizationnon-static

Static and non-static synchronization, why the output results differ?


Why is there a difference in output? I have 2 cases:

  1. In first case I use static functions f1 and f2:
    public static synchronized void f1() {
        for (int i = 0; i < 100; i++)
            System.out.print("A");
    }
    
    public static synchronized void f2() {
        for (int i = 0; i < 100; i++)
            System.out.print("B");
    }
    
    Here is my main method body:
    Thread t1 = new Thread(
            new Runnable(){public void run(){f1();}}
    );
    
    Thread t2 = new Thread(
            new Runnable(){public void run(){f2();}}
    );
    t1.start();
    t2.start();
    
    the output is:
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
    
  2. In the second case f1 and f2 are not static:
    public synchronized void f1() {
        for (int i = 0; i < 100; i++)
            System.out.print("A");
    }
    
    public synchronized void f2() {
        for (int i = 0; i < 100; i++)
            System.out.print("B");
    }
    
    the output is so messy:
    AAABABABBBBAAAAAAAAAABBAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBAA
    

Solution

  • Static synchronized functions synchronize on the class while non-static synchronized functions synchronize on the instance.

    This means that when the functions are static they block each other while when they're not (and use different instances) they don't.

    If your class is called MyClass then:

    public static synchronized foo() {...}
    

    Is similar to:

    public static foo() {
        synchronized (MyClass.class) {
            // ...
        }
    }
    

    While :

    public synchronized foo() {...}
    

    Is similar to:

    public foo() {
        synchronized (this) {
            // ...
        }
    }
    

    Generally you want to specify what you're synchronizing on (what resource do you want to hold exclusively?) and avoid using the implicit synchronization on the class/instance because of this reason exactly.