Paul C
Paul C

Reputation: 8457

Is a direct assignment of a volatile variable thread safe? As safe as an AtomicReference?

Is this as safe as using an AtomicReference?

private volatile String myMember;

public void setMyMember(String s) { 
   myMember = s;
}

vs.

private final AtomicReference<String> myMember = new AtomicReference<>();

public void setMyMember(String s) {
    while (true) {
        String current = myMember.get();
        if (myMember.compareAndSet(current, s))
            break;
    }
}    

Upvotes: 1

Views: 1265

Answers (2)

Gray
Gray

Reputation: 116878

Your code is "safe" but doesn't do the same thing as the AtomicReference code. Typically, the AtomicReference loop with compareAndSet is used when someone is trying to add something to a list or object and they want to protect against the race conditions with multiple threads.

For example:

private final AtomicReference<List<String>> listRef = new AtomicReference<>();
...
while (true) {
    List<String> currentList = listRef.get();
    List<String> newList = new ArrayList<String>(currentList);
    newList.add(stringToAdd);
    // if we update the list reference, make sure we don't overwrite another one
    if (listRef.compareAndSet(currentList, newList))
        break;
}

In your case, since you are using a simple String object, just making it volatile will be fine. There is no point in doing the compareAndSet. If you still want to use AtomicReference, then just call myMember.set(...).

Upvotes: 5

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

Your first code snippet is completely thread safe and is enough because String is thread safe and assigning to variable is atomic.

The second one doesn't make much sense, such construct is used internally e.g. in AtomicInteger to avoid ignoring assignments in concurrent environment. volatile is fine in your case.

Upvotes: 3

Related Questions