Skip to content

Stats based on LongAdder can return unexpected values #52411

@ywelsch

Description

@ywelsch

We expect certain stats values to be non-negative when serializing them over the wire. While investigating a test failure (#52406), I noticed that, due to concurrency, counts from LongAdder can be inexact, and even be negative even though in a properly serialized execution no such negative value should be observable.

Here's a test illustrating the issue:

    public void testConcurrentLongAdderAccess() throws InterruptedException {
        AtomicBoolean stopped = new AtomicBoolean();
        LongAdder longAdder = new LongAdder();

        Thread[] writers = new Thread[10];
        for (int i = 0; i < writers.length; i++) {
            writers[i] = new Thread(() -> {
                while(stopped.get() == false) {
                    longAdder.increment();
                    longAdder.decrement();
                }
            });
            writers[i].start();
        }

        Thread[] readers = new Thread[10];
        for (int i = 0; i < writers.length; i++) {
            readers[i] = new Thread(() -> {
                while(stopped.get() == false) {
                    long val = longAdder.longValue();
                    assert val >= 0L : "expected positive but got " + val;
                }
            });
            readers[i].start();
        }

        Thread.sleep(10000);

        stopped.set(true);

        for (int i = 0; i < writers.length; i++) {
            writers[i].join();
        }

        for (int i = 0; i < readers.length; i++) {
            readers[i].join();
        }
    }

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions