Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do volatile variables require synchronized access?

I'm having a little difficulty understanding volatile variables in Java.

I have a parameterized class that contains a volatile variable like so:

public class MyClass<T> {

    private volatile T lastValue;

    // ... other code ...

}

I have to implement certain basic operations against lastValue including a get-value-if-not-null.

Do these operations need to be synchronized? Can I get away with doing the following method?

public void doSomething() {
    String someString;
    ...
    if (lastValue != null) {
        someString += lastValue.toString();
    }
}

Or do I need to stick the null check into a synchronized block?

public void doSomething() {
    String someString;
    ...

    synchronized(this) {
        if (lastValue != null) {
            someString += lastValue.toString();
        }
    }
}

I know that for atomic operations like get and set, I should be ok without applying synchronization (eg. public T getValue() { return lastValue; } ). But I wasn't sure about non-atomic operations.

like image 838
Roddy of the Frozen Peas Avatar asked Jun 06 '13 15:06

Roddy of the Frozen Peas


1 Answers

volatile guarantees visibility (changes made by one thread will be seen by other threads) but it does not guarantee atomicity of several operations.

So yes, lastValue could become null between if (lastValue != null) and someString += lastValue.toString(); and your code could throw a NullPointerException.

You can either add synchronization (but you will need to synchronize all write accesses to the variable), or for that simple use case, you can use a local variable:

public void doSomething() {
    String someString;
    T lastValueCopy = lastValue;
    if (lastValueCopy != null) {
        someString += lastValueCopy.toString();
    }
}
like image 176
assylias Avatar answered Oct 13 '22 13:10

assylias