可以使用volatile字段修饰符替换同步读取吗?

时间:2019-07-05 14:18:31

标签: java concurrency synchronization

在阅读接受的答案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;
        }
    }
}

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

提前谢谢

1 个答案:

答案 0 :(得分:1)

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

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

最后一点要注意,synchronized块的进度条件与volatile的读写条件不同。前者阻止(互斥),而后者则无需等待。