Payel Senapati
Payel Senapati

Reputation: 1356

Not getting desired result when using synchronized keyword in Java multithreading

I have two files, App.java and Runner.java

App.java -->

public class App {
    private static Thread thread1 = new Runner(1);
    private static Thread thread2 = new Runner(2);

    public static void main(String[] args) throws InterruptedException {
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.printf("Count = %d\n", Runner.getCount());
    }
}

Runner.java -->

public class Runner extends Thread {
    private volatile static int count = 0;
    private int option = 0;

    private synchronized void increment() {
        count++;
    }

    private synchronized void decrement() {
        count--;
    }

    public Runner(int option) {
        this.option = option;
    }

    public static int getCount() {
        return count;
    }

    @Override
    public void run() {
        switch (option) {
            case 1:
                for (int i = 1; i <= 10000; i++) {
                    increment();
                }
                break;
            case 2:
                for (int i = 1; i <= 10000; i++) {
                    decrement();
                }
                break;
        }
    }
}

Here I am trying to create two threads from main thread and access a common variable from both the threads where both the threads will manipulate this common variable at the same time.

I am trying to create a demo for implementation for the synchronized keyword.

In my example, in Runner.java -

I am making Runner class a child class of Thread using extends keyword and overriding the run() method in body.

Next, I am using a constructor to get an option and running the respective code in run() method in a switch - case block. The common variable is count which is static with initial value 0.

There are two methods, both use the synchronized keyword - increment() and decrement() which increase and decrease the value of count by 1 respectively.

For option 1 run() method uses a for loop to run increment() 10,000 times. For option 2 run() method uses a for loop to run decrement() 10,000 times.

As such the end value of count should be 0.

In App.java -

I am creating two threads - thread1, thread2 which are instances of Runner class and passing constructor argument 1 and 2 respectively.

I am running the two threads using thread.start() and waiting for completion of the two threads using thread.join()

Now, I am printing the value of count. The value is expected to be 0. But it is not. In each execution it is near to 0 but not 0.

So, where am I going wrong and how to correct my code?

Upvotes: 1

Views: 31

Answers (1)

Piotr Praszmo
Piotr Praszmo

Reputation: 18320

count is static meaning there is only one such variable. Both increment and decrement are not static which means they are synchronized on this - that is two separate Runner instances.

Make those method static:

private synchronized static void increment() {
    count++;
}

private synchronized static void decrement() {
    count--;
}

or use explicit mutex object:

private static int count = 0;
private static Object mutex = new Object;

private int option = 0;

private void increment() {
    synchronized (mutex) {
        count++;
    }
}

private void decrement() {
    synchronized (mutex) {
        count--;
    }
}

Upvotes: 1

Related Questions