Dear Experts, In my following code I have createed a synchronized method called print() within class Printer. Two threads are accessing the same printer instance and doing their printing job. Even if print() is synchronized, it allows both the threads to enter inside. But if I change my code with synchronized block by getting a lock Printer.class, one thread enters at a time. Why it is so?
I have an understanding that with a synchronized print() method I should be able to controll entering of one thread at a time, which seems to be not correct.
public class TestSync { Printer printer = new Printer(); public static void main(String[] args) { ThreadA a = new TestSync().new ThreadA(); //a.setName("Manoj"); ThreadB b = new TestSync().new ThreadB(); //b.setName("Gopi"); b.start(); a.start(); }
class ThreadA extends Thread { public void run() { //synchronized (Printer.class) { printer.print(); //} } } class ThreadB extends Thread { public void run() { //synchronized (Printer.class) { printer.print(); //} } } } class Printer { public synchronized void print() { for (int i = 0; i < 10; i++) { System.out.println("I am in " + Thread.currentThread().getName()); try{ Thread.sleep(100); }catch(InterruptedException e){} } } }
output -------- I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0 I am in Thread-1 I am in Thread-0
Your trouble has to do with what you are synchronizing on.
When you add the synchronized keyword on an instance method, you are synchronizing on the instance of that class.
Earlier, when you called:
ThreadA a = new TestSync().new ThreadA(); ThreadB b = new TestSync().new ThreadB();
There were two instances of TestSync and therefore two instances of the printer class. Your threads seemed to be independent because they were using two different classes for locking.
When you instead synchronize on Printer.class, you are synchronizing on a single instance. As odd as it may sound, Printer.class is a class itself which has nothing to do with your individual instances.