是否直接赋值volatile变量线程安全?像AtomicReference一样安全吗?

时间:2021-12-31 21:00:48

Is this as safe as using an AtomicReference?

这和使用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;
    }
}    

2 个解决方案

#1


5  

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.

您的代码是“安全的”但与AtomicReference代码不同。通常,当有人试图向列表或对象添加内容并且他们想要防止多线程的竞争条件时,使用带有compareAndSet的AtomicReference循环。

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(...).

在您的情况下,因为您使用的是简单的String对象,所以只需将其设置为volatile即可。做compareAndSet没有意义。如果您仍想使用AtomicReference,则只需调用myMember.set(...)。

#2


3  

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

你的第一个代码片段完全是线程安全的,因为String是线程安全的,并且分配给变量是原子的。

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.

第二个没有多大意义,这种结构在内部使用,例如在AtomicInteger中,以避免忽略并发环境中的赋值。在你的情况下,挥发性很好。

#1


5  

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.

您的代码是“安全的”但与AtomicReference代码不同。通常,当有人试图向列表或对象添加内容并且他们想要防止多线程的竞争条件时,使用带有compareAndSet的AtomicReference循环。

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(...).

在您的情况下,因为您使用的是简单的String对象,所以只需将其设置为volatile即可。做compareAndSet没有意义。如果您仍想使用AtomicReference,则只需调用myMember.set(...)。

#2


3  

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

你的第一个代码片段完全是线程安全的,因为String是线程安全的,并且分配给变量是原子的。

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.

第二个没有多大意义,这种结构在内部使用,例如在AtomicInteger中,以避免忽略并发环境中的赋值。在你的情况下,挥发性很好。