-1

Below code doesn't give synchronized output.

public class MultiThr implements Runnable{

public static void main(String[] args) {

    for(int i = 0;i < 5;i++){
        new Thread(new MultiThr()).start();
    }
}

@Override
public void run() {

    increment();
}

public synchronized void increment(){
    for(int i=0;i<10;i++){
        System.out.println(i);
        try {
            Thread.sleep(400);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
}

Could anybody explain me how to get object lock on increment() method?

Sandeep Samal
  • 143
  • 1
  • 8

2 Answers2

0

This usage of the synchronized keyword causes the method to acquire a lock on the object that the method is being invoked on. Since you have 5 MultiThr objects, that's 5 different objects that are being locked.

There are a number of options to fix this, for instance you could create an object that to be shared among all MultiThr objects:

public class MultiThr implements Runnable{
    private static final Object lock = new Object();

    public static void main(String[] args) {
        for(int i = 0;i < 5;i++){
            new Thread(new MultiThr()).start();
        }
    }

    @Override
    public void run() {
        increment();
    }

    public void increment(){
        synchronized (lock) {
            for(int i=0;i<10;i++){
                System.out.println(i);
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {}
            }
        }
    }
}
Floegipoky
  • 3,087
  • 1
  • 31
  • 47
-1

your increment() method is synchronized. Your problem is that it is a part of your Runnable. More of that, your counter variable i is a local variable, so each thread will have it's own copy of i even without the synchronized keyword. What I would recommend you to do is to create a class MyConter like:

class MyCounter {   

    private int i;

    public MyCounter () {
        i = 0;
    }

    public int getCounter() {
        return i;
    }

    public void increment() {
        i++;
    }
}

Then pass it as an argument to the MultiThr constructor:

public class MultiThr implements Runnable{

    private MyCounter counter;

    public MultiThr(MyCounter counter)  {
        this.counter = counter;
    }

    @Override
    public void run() {  
        increment();
    }

    public synchronized void increment(){
        for(int i=0;i<10;i++){
            counter.increment();
            System.out.println(counter.getCounter());
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                // Do not do just e.printStackTrace()
                Thread.currentThread().interrupt()
            }
        }
    }

    public static void main(String[] args) {
        for(int i = 0;i < 5;i++){
           new Thread(new MultiThr()).start();
        }
    }
}

Or you can use AtomicInteger instead of MyCounter, just make sure that the same instance is passed to each thread.

mp_loki
  • 1,018
  • 1
  • 10
  • 21