出于明显的原因,下面的代码(Java Concurrency in Practice清单16.3)不是线程安全的:
public class UnsafeLazyInitialization {
private static Resource resource;
public static Resource getInstance() {
if (resource == null)
resource = new Resource(); // unsafe publication
return resource;
}
}
但是,在几页之后的16.3节中,它们指出:
UnsafeLazyInitialization
如果Resource
是不变的,则实际上是安全的。
我不明白那句话:
Resource
是不可变的,则任何观察该resource
变量的线程都将看到该变量为null或已完全构建(由于Java内存模型提供了对最终字段的有力保证)resource
可重新排序(存在于一个读if
,一个在return
)。因此,线程可以resource
在if
条件中看到非null ,但返回null引用(*)。我认为UnsafeLazyInitialization.getInstance()
即使Resource
不可变也可以返回null
。是这样吗,为什么(或者为什么不是)?
(*)为了更好地理解我有关重新排序的观点,Jeremy
Manson的这篇博客文章是JLS关于并行性的第17章的作者之一,他解释了如何通过良性数据竞赛安全地发布String的哈希码,以及如何删除局部变量的使用可能导致哈希码错误地返回0,这是由于可能的重新排序与我在上文所述非常相似:
我在这里所做的是添加一个附加读取:哈希的第二次读取,即返回之前。听起来很奇怪,但不太可能发生,第一次读取可以返回正确计算的哈希值,而第二次读取可以返回0!内存模型允许这样做,因为该模型允许对操作进行广泛的重新排序。实际上,第二个读取可以在您的代码中移动,因此您的处理器可以在第一个读取之前完成它!
我认为您的困惑是作者安全发表的意思。他指的是非空资源的安全发布,但是您似乎明白了。
您的问题很有趣-是否可以返回资源的空缓存值?
是。
允许编译器像这样重新排序操作
public static Resource getInstance(){
Resource reordered = resource;
if(resource != null){
return reordered;
}
return (resource = new Resource());
}
这不违反顺序一致性规则,但可以返回空值。
这是否是最好的实现尚待争论,但没有规则可以阻止这种重新排序。
a)为什么除了“00”之外还有其他输出? b)如何修改代码以便始终打印“00”。 对于a)我的回答是:在没有任何volatile/同步构造的情况下,编译器可以重新排序一些指令。特别是“this.initialint=val;”和“this.flag=true;”可以切换,这样就可以发生这种情况:线程都启动了,t1充电在前面。给定重新排序的指令,它首先设置flag=true。在它到达“this.in
其中导入包括DAOs的Spring配置,在applicationContext-data.xml中我有: 当我运行项目服务的单元测试时,一切都很好,所有变量都正确地解析了,没有任何问题。但是当我运行project-web(project-service将作为。jar文件包含在project-web的WEB-INF/lib文件夹中)时,它会在启动过程中抛出错误,说不能解析${db.type}: or
问题内容: 如何在不更改HTML源代码的情况下重新排序div? 例如,我希望div以#div2,#div1,#div3的顺序显示,但是在HTML中它们是: 谢谢! 问题答案: 没有使用css对元素进行重新排序的万能方法。 您可以通过将它们全部向右浮动来水平反转它们的顺序。或者,您可以将它们相对于正文或其他包含元素的绝对位置进行定位- 但这对元素的大小以及相对于页面上其他元素的位置存在严格的限制。
问题内容: 我只是碰到一篇文章,声称我从未听过,也找不到其他地方。声称是从另一个线程的角度来看,可以根据构造函数内部的指令对构造函数返回的值的分配进行重新排序。换句话说,声称是在下面的代码中,另一个线程可以读取其中未设置的非空值。 这是真的? 编辑: 我认为从线程执行的角度来看,可以保证的分配与的分配具有先发生后关系。但是,这两个值都可能缓存在寄存器中,并且可能未按照最初写入的顺序将它们刷新到主存
我正在尝试使用Apache Camel运行一个简单的重新排序程序。该程序使用Java DSL对传入的Java消息重新排序。当我运行这个程序时,消息会被写入文件夹,但根据标题值或消息正文中单个单词的字母顺序,不会出现任何特定的顺序。Camel创建的文件仍然无序,就好像DSL函数什么都没做一样。 如何让这个程序像方法那样对消息进行实际排序?此外,如何让这个程序重新排序,然后以正确的排序顺序将消息聚合到
我决定要对一个特定的函数进行基准测试,所以我天真地编写了这样的代码: 一位同事指出,我应该将和变量声明为,以避免代码重新排序。例如,他建议优化器可以像这样有效地重新排序代码: 起初,我怀疑这种极端的重新排序是允许的,但经过一些研究和实验,我知道是允许的。 但volatile感觉不是正确的解决方案;volatile真的只是用于内存映射I/O吗? 然而,我添加了< code>volatile,发现不仅