我想了解为什么声明为final的Reference不能声明为Volatile.在SO上有一个类似的问题[ 为什么Object成员变量在Java中不是最终的和易变的?
[1]:为什么Object成员变量在Java中不能是final和volatile?但我不确定在答案中是否理解了FINAL.
现在,最终变量的状态在初始化后肯定可以更改.只能将引用初始化为另一个对象.
例如,考虑以下成员变量
final StringBuilder sb = new StringBuilder("CAT");
Run Code Online (Sandbox Code Playgroud)
现在另一个线程改变sb为:
sb.append("S");
Run Code Online (Sandbox Code Playgroud)
如果此变量是非易失性的,那么根据Java内存模型,此更改是否可用于不同的线程?
编辑:我把StringBuffer改为StringBuilder让一些人明白我的观点.
Joh*_*int 16
volatile意味着该领域将发生变化.如果它是最终的,你将永远不会改变它,这是没有意义的.
如果此变量是非易失性的,那么根据Java内存模型,此更改是否可用于不同的线程?
在发生易失性写入后,声明字段volatile对其内容或修改没有影响.如果字段是易失性或非易失性,则内存效应append由StringBuffer的实现决定.
因此,在StringBuffer的情况下,它确实可以确保内存可见性,但不是出于您的想法.StringBuffer是同步的(线程安全的),因此您将拥有内容的始终最新值.
另一方面,StringBuilder未同步,并且无法保证内存可见性.因此,如果您尝试将两者交换为多线程测试,您会看到不同的结果.
因为volatile影响Threads访问和编辑变量的行为.在您的代码示例中,变量是sb对象的reference().因此,这意味着volatile有没有对效果的对象.final锁定引用.因此,如果您附加文本,则不会更改引用.因此,它是没有意义的使用volatile,并final在同一时间.
如果此变量是非易失性的,那么根据Java内存模型,此更改是否可用于不同的线程?
因为您使用StringBuilder使用非线程安全实现,所以无法保证所有线程都具有StringBuilder的最新状态.
如果此变量是非易失性的,则根据Java内存模型,此更改是否可用于不同的线程
是的,但那是因为StringBuffer是线程安全的 - 这意味着它在内部提供锁定,这将导致内存障碍,以便其他线程看到更新.
volatile是一个引用不会影响对象的操作,它会影响引用.
所以你可以做到
volatile StringBuilder b = new StringBuilder();
b = someOtherStringBuilder;
Run Code Online (Sandbox Code Playgroud)
既然b是volatile,其他线程会看到这个引用的更新.
无论如何
b.append("foo");
Run Code Online (Sandbox Code Playgroud)
无法保证其他线程会看到对现有b对象的更改.与StringBuffer不同,StringBuilder不是线程安全的,所以如果不提供自己的锁定,你不应该这样做.
如果您希望保证b.append("foo");在没有任何锁定的情况下对其他线程可见,则StringBuilder中的每个成员字段也需要是volatile.(虽然这不会使线程安全)
请记住,volatile并final影响变量/成员,但不影响其中命名/引用的对象的可变性(或操作的线程安全性)!(其他答案解释了为什么修饰符不能一起使用。)
在给定的情况下,sb.append(..) 修改命名/引用对象(尽管它不会修改变量/成员)并且不安全 使用任一修饰符进行跨线程。
正如其他人指出的那样,StringBuilder添加了一些内部同步,但这仅意味着它不会在其内部数据结构级别上“变得损坏”。
但是,切换到StringBuilder仍然不是 “固有”线程安全的。线程安全性与各种动作的原子范围有很大关系-并且在没有看到所有活动的情况下进行判断以及如何允许其以有效执行方式进行交互将产生误导。
例如,考虑以下从多个线程执行的代码(并假定sb现在是StringBuilder对象)。订单是什么?
sb.append("a").append("b");
Run Code Online (Sandbox Code Playgroud)
如果代码更改如下,会发生什么?[更多]“线程安全”是哪个?
synchronized (this) {
sb.append("a").append("b");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3434 次 |
| 最近记录: |