Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Java unexpected concurrent result

While testing concurrency, I found something unexpected.

Concurrency was controlled using concurrentHashMap and AtomicLong.

public class HumanRepository {

    private final static Map<Long, Human> STORE = new ConcurrentHashMap<>();
    private AtomicLong sequence = new AtomicLong();

    public void save(Human human) {
        STORE.put(sequence.incrementAndGet(), human);
    }

    public int size() {
        return STORE.size();
    }


    public Long getSeq() {
        return sequence.get();
    }
}

I tested saving in multiple threads.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    @Test
    void name() throws NoSuchMethodException, InterruptedException {
        final int threads = 3_500;
        final ExecutorService es = Executors.newFixedThreadPool(threads);
        final CountDownLatch count = new CountDownLatch(threads);
        final HumanRepository repository = new HumanRepository();

        for (int i = 0; i < threads; i++) {
            try {
                es.execute(() -> repository.save(new Human("aa")));
            } finally {
                count.countDown();
            }
        }

        count.await();

        System.out.println("seq = " + repository.getSeq());
        System.out.println("size = " + repository.size());
    }

I tested it with 3500 threads simultaneously. The result I expected is 3500 for both seq and size.

But sometimes I get seq=3499, size=3500.
That’s weird. It is strange that seq does not come out as 3500, and even though the size is 3500, it does not make sense that seq is 3499.

I don’t know why the data number and seq in the map are not the same and 3500 is not coming out.

** If you do Thread.sleep(400L); after count.await();, surprisingly, the value of seq is 3500

enter image description here

>Solution :

You are not actually waiting for all tasks to complete. Which means that if you get the 3500/3500 output, it’s by chance.

Specifically, you decrease the countdown latch on the main thread after scheduling the job, instead of inside of the job, once it’s done. That means your countdownlatch is basically just another glorified loop variable that doesn’t do any inter-thread communication. Try something like this instead:

    for (int i = 0; i < threads; i++) {
        es.execute(() -> {
          repository.save(new Human("aa"));
          count.countDown();
        });
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading