【问题标题】:Can synchronized read be replaced with volatile field modifier?可以用 volatile 字段修饰符替换同步读取吗?
【发布时间】:2019-07-05 14:18:31
【问题描述】:

在阅读接受的答案How to synchronize or lock upon variables in Java? 时,我想到如果在下面的示例中使用 volatile 而不是同步块,行为是否会改变。我想确保消息始终返回正确的值。

让我使用同样的示例:请注意,现在我已经删除了 get 方法中的同步块,并将变量消息标记为 volatile。

class Sample {
    private volatile String message = null;
    private final Object lock = new Object();

    public void newMessage(String x) {
        synchronized (lock) {
            message = x;
        }
    }

    public String getMessage() {
            return message;
        }
    }
}

如果要更改如上所示的代码,是否会保证相同的行为?两种方法之间有什么区别吗?

提前谢谢你

【问题讨论】:

  • 是的,如果是单个变量,那么 synchronized 块是不必要的,而 volatile 写入就足够了。
  • 谢谢埃里克。你是说当变量被标记为 volatile 时我根本不需要读取和写入同步?

标签: java concurrency synchronization


【解决方案1】:

在这种情况下,volatile 关键字就足够了,因为它为读取和写入建立了发生前的关系,保证了一个线程中的写入将被另一个线程中的后续读取观察到。

synchronized 块不正确,但它是多余的。此外,如果您使用synchronized,您可以将您的消息变量标记为非易失性。但要小心并确保读取也在synchronized 块中,否则您将遇到数据竞争。 synchronized 块中的一个线程进行的非易失性写入保证对随后进入同一监视器上的synchronized 块的线程可见。

最后一点,synchronized 块的进度条件与 volatile 读写不同。前者阻塞(互斥),后者无等待。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多