某些语言提供的volatile修饰符被描述为在读取支持变量的内存之前执行"读取内存屏障".
读取存储器屏障通常被描述为一种方法,用于确保CPU在屏障之后执行读取之前执行读取之前所请求的读取.但是,使用此定义,似乎仍然可以读取过时值.换句话说,以特定顺序执行读取似乎并不意味着必须查询主存储器或其他CPU以确保读取的后续值实际上反映了读取屏障时系统中的最新值或随后写入阅读障碍.
因此,volatile是否真的保证读取最新值或者只是(喘气!)读取的值至少与屏障之前的读取一样是最新的?还是其他一些解释?这个答案有什么实际意义?
重要编辑我知道在发生两个赋值的线程中 "发生在之前" 我的问题是,另一个线程是否可能读取"b"非空,而"a"仍为空.所以我知道如果你从与之前调用setBothNonNull(...)的线程相同的线程调用doIt(),那么它就不能抛出NullPointerException.但是如果一个人从另一个线程调用doIt()而不是调用setBothNonNull(...)的那个呢?
请注意,这个问题仅仅是对volatile关键字和volatile保证:这是不是对synchronized关键字(所以请不要回答"您必须使用同步"因为我没有任何问题要解决:我只是想了解volatile担保关于无序执行(或缺乏保证).
假设我们有一个包含两个volatileString引用的对象,它们被构造函数初始化为null,并且我们只有一种方法来修改两个String:通过调用setBoth(...)并且我们之后只能将它们的引用设置为非null引用(只允许构造函数将它们设置为null).
例如(这只是一个例子,毫无疑问):
public class SO {
private volatile String a;
private volatile String b;
public SO() {
a = null;
b = null;
}
public void setBothNonNull( @NotNull final String one, @NotNull final String two ) {
a = one;
b = two;
}
public String getA() …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我需要能够交换集合中的元素.所以我有一个选择:
valvar永久集合(并始终重新分配新集合var)但是在Scala中(在函数式编程中),可变性总是避免.那么更糟糕的是:使用声明的可变集合val或声明为不可变的集合var?