java - volatile 变量是否需要同步访问?

标签 java synchronization thread-safety synchronized volatile

我在理解 Java 中的 volatile 变量时遇到一点困难。

我有一个参数化类,其中包含一个 volatile 变量,如下所示:

public class MyClass<T> {

    private volatile T lastValue;

    // ... other code ...

}

我必须针对 lastValue 实现某些基本操作,包括 get-value-if-not-null。

这些操作需要同步吗?我可以通过以下方法逃脱吗?

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

或者我是否需要将空检查粘贴到同步块(synchronized block)中?

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

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

我知道对于像 get 和 set 这样的原子操作,我应该可以不应用同步(例如 public T getValue() { return lastValue; } )。但我不确定非原子操作。

最佳答案

volatile 保证可见性(一个线程所做的更改将被其他线程看到)但它不保证多个操作的原子性。

是的,lastValue 可以在 if (lastValue != null)someString += lastValue.toString( ); 并且您的代码可能会抛出 NullPointerException

您可以添加同步(但您需要同步对变量的所有写访问),或者对于那个简单的用例,您可以使用局部变量:

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

关于java - volatile 变量是否需要同步访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16965724/

相关文章:

java - 如何从父类获取执行的Java子类名?

java - 如何使用 Maven 将文件添加到类路径而不添加到 jar 中?

java - Spring Boot 2异步进行调用但不返回响应

ios - 同步录音/回放ios

Java : Multi-threaded linked list access synchronization

Java线程同步对象的等待和通知

java - 切换 LinearLayout 的不可见和可见

c++ - std::queue pop 推送线程安全

java - Android:线程没有更新值

Cocoa:以最轻量级的方式同步访问 double?