I'm just a Greenhorn but to teach is to learn...
Threads calling non-static synchronized methods in the same class will
only block each other if they're invoked using the same instance and if
they're called using two different instances, they get two locks, which do not interfere with each other.
Quick review:
non-static methods are instance methods and execute within the scope of the instance.static methods are class methods and execute within the scope of the class.
Your quote states that the threads are calling non-static or instance methods and not class methods. I'll cover both but first non-static methods.
In order to execute instance methods you need to create an instance. For example MyClass newInstance = new MyClass();
Lets say that MyClass has a non-static synchronized method as follows;
public synchronized void instanceSyncMethod() { System.out.println("calling instanceSyncMethod()"); }
newInstance is now an object with its own variables and methods. If newInstance is passed to two threads running simultaneously then both threads are using the same instance. So when thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance.instanceSyncMethod() they are both asking the same object to do the same thing. Because the method is synchronized meaning only one thread can execute the code at a time the first thread to obtain the lock will execute and the second thread will need to wait/block.
Lets create another instance of MyClass and call it newInstance2 - MyClass newInstance2 = new MyClass()
newInstance2 is a separate copy of MyClass and has its own variables and methods. Now pass newInstance to thread1 and newInstance2 to thread2. When thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance2.instanceSyncMethod() the two threads are calling the same method but on two different instances. Since each instance has its own variables and methods the threads run without blocking.
Hopefully that makes the non-static part clearer.
The static part requires that you change the scope (and thinking) from instance to class.
Lets say that MyClass has a static synchronized method as follows;
public static synchronized void staticSyncMethod() { System.out.println("calling MyClass.staticSyncMethod()"); }
We have already seen that when thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance2.instanceSyncMethod() that the two threads run without blocking. But what happens when they both call staticSyncMethod() even on different instances of MyClass?
Because staticSyncMethod() is a static method only one copy of this method will ever exist and is referenced from the MyClass object. In fact when thread1 or thread2 calls newInstance.staticSyncMethod() the compiler is building a call to MyClass.staticSyncMethod(). The ability to use newInstance or newInstance2 to reference staticSyncMehtod() is allowed by the compiler as a convenience method but the code generated always translates the code to reference the class object.
If you were to correctly program the code thread1 would call:
MyClass.staticSyncMethod();
and thread2 would call:
MyClass.staticSyncMethod();
It makes it easier to see that both threads are calling the same method in the same scope and by calling this method one thread would need to block as the other executed.
Make sense?