Question

I am trying to understand thread synchronization in java below is the code there is a main class with the name Interview. In that class I am creating two objects

public class Interview{

    /**
     * @param args the command line arguments
     * @throws java.lang.InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO code application logic here\
        Race r1=new Race();
        r1.setA(15);
        Thread t1=new Thread(r1, "First thread");
        Race r2=new Race();
        r2.setA(25);

        Thread t2=new Thread(r2, "Second thread");
        t1.start();
        t2.start();
        }
}

There is other class that has the run method with the name Race here is the code

public class Race implements Runnable{
    int a;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
    @Override
    public void run() {
        try {

                print();



        } catch (InterruptedException ex) {
            Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   public synchronized void print() throws InterruptedException{
       for(int i=1;i<=10;i++){
           System.out.println(a*i);
           Thread.sleep(1000);
       }

   }
}

For every object I am giving different values of a and then trying to have print method synchronized but its not working. The concept that I am using is two threads that are trying to access a shard resource simultaneously can't do so by using synchronized method. So in my case two threads t1 and t2 trying to access print method simultaneously so I am using synchronized keyword with print method but still the result is same. What I want is thread t1 to execute first i,e. 15 30 45 60..... then thread t2 i.e, 25 50 75... and so on. Correct me if my concept is unclear..

Was it helpful?

Solution

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.

OTHER TIPS

The rule is actually that two methods that are synchronized on the same object cannot run simultaneously.

A non-static method that is declared synchronized synchronizes on its object, so the print() method in each Race synchronizes on its own Race object.

You can declare a synchronized block containing the body of the method that synchronizes on a shared object, such as Race.class.

public class Race implements Runnable {
    private final Object lock;

    public Race(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            print();
        } catch (InterruptedException ex) {
            Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void print() throws InterruptedException {
        synchronized(lock) {
            for(int i = 1; i <= 10; i++){
                System.out.println(i);
                Thread.sleep(1000);
            }
        }
    }
}

public class Interview{
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();

        Race r1 = new Race(lock); // <== lock object
        Thread t1 = new Thread(r1, "First thread");

        Race r2 = new Race(lock); // <== same lock object
        Thread t2 = new Thread(r2, "Second thread");

        t1.start();
        t2.start();
    }
}

It cannot be guaranteed which thread will be executed first.It is upto the JVM to decide which thread will begin first. As you say What I want is thread t1 to execute first i,e. 15 30 45 60..... then thread t2 i.e, 25 50 75... and so on you can use the join() method. It will make sure that other thread will be executed only after the thread joining it has completed. For more information refer this .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top