Search code examples
javamultithreadingmemoryconcurrencyvolatile

Is this object modified in listener threadsafe?


In the following snippet, assume two threads read/write from/to results. When the eventListener thread writes to results, will the blocked thread be able to access the latest results? If not, what utility (volatile, AtomicReference) will help?

private Object doStuff() {

    CountDownLatch latch = new CountDownLatch( 1 );
    Object[] results = new Object[1];

    EventObjectListener eventListener = ( String topic, Object eventObject ) -> {
        results[0] = eventObject;
        latch.countDown();
    };

    eventReceiver.addEventListener( eventListener );

    doThingThatGeneratesEvent();

    int waitMagnitude = 10;
    TimeUnit waitUnit = TimeUnit.SECONDS;
    try {
        latch.await( waitMagnitude, waitUnit );
    } catch ( InterruptedException e ) {
        return null;
    } finally {
        eventReceiver.removeEventListener( eventListener );
    }

    return results[0];
}

Solution

  • Yes, the CountDownLatch guarantees visibility¹, so if await doesn't time out results[0] will be good to go. However the code could probably be rewritten to be a little clearer.

    ¹ i.e. all writes from thread before countDown() happen before the other thread returns from the await() call.


    A slightly clearer (IMHO) version would use a CompletableFuture as follows:

    CompletableFuture<Object> future = new CompletableFuture();
    
    EventObjectListener eventListener = (topic, eventObject) -> 
            future.complete(eventObject);
    
    try {
        return future.get(waitMagnitude, waitUnit);
    } catch(Exception e) {
        return null;
    } finally {
        eventReceiver.removeEventListener(eventListener);
    }