Your synchronized method is an instance method. That means the lock obtained for synchronization is obtained over the instance itself. Thus, when your threads run, one obtains a lock over r1, and the other over r2. Therefore, it is working fine, it is just not what you were expecting.
It looks like you wanted to create mutual exclusion between r1 and r2. For that, your method needs to be static, so that the lock is obtained over the class object. Or you would need to use a different lock object, shared by both threads (which based solely on your example looks unnecessary).
In other words, your threads are not sharing the same object, therefore, there isn't any race condition between them.
For instance, you could create mutual exclusion either by making both threads use the same instance of Race or by creating a mutual exclusion object shared by both.
Like so:
class Race {
public void synchronized print(){
...
}
}
Race r = new Race();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r); //notice both threads share r.
t1.start();
t2.start();
In the example above, both threads will try to run the print method on the same object. This means, the synchornized
keyword is creating a mutual exclusion block here. Only one thread at the time can obtain the lock over the race object.
If you use two different instances of Race, then there is no point in creating a mutual exclusion. Since there is no race condition, there is no point in making the threads coordinate between each other. That would just delay them without any need.