This question already has answers here:
Why can an Object member variable not be both final and volatile in Java?
(7个答案)
7年前关闭。
我想理解为什么为什么声明为final的引用不能声明为Volatile。关于SO [Why can an Object member variable not be both final and volatile in Java?
[1]:Why can an Object member variable not be both final and volatile in Java?,但我不确定该答案是否理解了FINAL。
现在,最终变量的状态可以在初始化后确定地更改。只有引用不能初始化为另一个对象。
例如考虑以下成员变量
现在另一个线程将sb更改为:
如果此变量为Non-Volatile,根据Java内存模型,此更改是否可用于不同的线程?
编辑:我将StringBuffer更改为StringBuilder,以使某些人明白我的观点。
现在,由于b是volatile,其他线程将看到此引用的更新。
但是做
无法保证其他线程会看到对现有
如果您想保证
(7个答案)
7年前关闭。
我想理解为什么为什么声明为final的引用不能声明为Volatile。关于SO [Why can an Object member variable not be both final and volatile in Java?
[1]:Why can an Object member variable not be both final and volatile in Java?,但我不确定该答案是否理解了FINAL。
现在,最终变量的状态可以在初始化后确定地更改。只有引用不能初始化为另一个对象。
例如考虑以下成员变量
final StringBuilder sb = new StringBuilder("CAT");
现在另一个线程将sb更改为:
sb.append("S");
如果此变量为Non-Volatile,根据Java内存模型,此更改是否可用于不同的线程?
编辑:我将StringBuffer更改为StringBuilder,以使某些人明白我的观点。
最佳答案
是的,但是那是因为StringBuffer是线程安全的-意味着它在内部提供锁定,这将导致内存障碍,因此其他线程可以查看更新。
可变的引用不会影响对象上的操作,而是会影响引用。
所以你可以做
volatile StringBuilder b = new StringBuilder();
b = someOtherStringBuilder;
现在,由于b是volatile,其他线程将看到此引用的更新。
但是做
b.append("foo");
无法保证其他线程会看到对现有
b
对象的更改。与StringBuffer不同,StringBuilder不是线程安全的,因此无论如何都不要提供自己的锁定,否则不要这样做。如果您想保证
b.append("foo");
对其他线程可见而没有任何锁定,则StringBuilder中的每个成员字段也需要是可变的。 (尽管这不能使其线程安全)