Home > Net >  Why does non-thread safe counter in Java always return the correct value?
Why does non-thread safe counter in Java always return the correct value?

Time:11-23

I'm trying to simulate a non-thread safe counter class by incrementing the count in an executor service task and using countdown latches to wait for all threads to start and then stop before reading the value in the main thread.

The issue is that when I run it the System.out at the end always returns 10 as the correct count value. I was expecting to see some other value when I run this as the 10 threads may see different values.

My code is below. Any idea what is happening here? I'm running it in Java 17 and from Intellij IDEA.

Counter.java

public class Counter {

    private int counter = 0;

    public void incrementCounter() {
        counter  = 1;
    }

    public int getCounter() {
        return counter;
    }
}

Main.java

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        CountDownLatch startSignal = new CountDownLatch(10);
        CountDownLatch doneSignal = new CountDownLatch(10);
        Counter counter = new Counter();
        for (int i=0; i<10; i  ) {
            executorService.submit(() -> {
                try {
                    startSignal.countDown();
                    startSignal.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                counter.incrementCounter();
                doneSignal.countDown();
            });
        }

        doneSignal.await();
        System.out.println("Finished: "   counter.getCounter());
        executorService.shutdownNow();
    }
}

CodePudding user response:

It's worth remembering that just because something isn't synchronised correctly, it could still perform correctly under some circumstances, it just isn't guaranteed to do so in every situation, on every JVM, on every hardware.

In other words, there is no reverse guarantee, optimisers for example are free to decide your code can be replaced at little to no cost with a correctly synchronised implementation.

(Whether that is what's actually happening here isn't obvious to me at first glance.)

  • Related