public Map<String, Date> lastLogin =
Collections.synchronizedMap(new HashMap<String, Date>())
由于引用字段lastLogin没有任何字段的属性来保证可见性(final、volatile、guarded或由静态初始化器初始化),我认为映射本身可能不会以完全构造的状态显示给其他线程,因此本末倒置。还是我错过了什么?
您的怀疑有一半是对的,因为lastlogin
的值不能保证对其他线程可见。因为lastlogin
不是volatile
或final
,所以另一个线程可能会将其读为null
。
但是,您不需要担心其他线程会看到一个不完整版本的映射。collections.synchronizedMap(...)
返回具有final
字段的私有类的实例。JLS第17.5节规定:
final字段的使用模型很简单:在对象的构造函数中设置对象的final字段;并且在对象的构造函数完成之前,不要在另一个线程可以看到的地方写入对正在构造的对象的引用。如果这样做,那么当另一个线程看到对象时,该线程将始终看到该对象最终字段的正确构造版本。
问题内容: 即使经过了这一点,我仍然不清楚在以下代码中使用final如何导致安全发布。有人可以给出一个易于理解的解释吗? 问题答案: 编辑添加:关于Java和JSR-133 行为起源的 有趣观点。 有关如何在新JMM中正常工作的规范参考,以确保安全发布:http : //www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRigh
问题内容: 在阅读了“ 实践中的Java并发 ”和“ 实践OSGI ”之后,我发现了一个非常有趣的特定主题。安全发布。以下是来自JCIP的内容: 为了安全地发布对象,必须同时使对该对象的引用和该对象的状态对其他线程可见。可以通过以下方式安全地发布正确构造的对象: 从静态初始化程序初始化对象引用。 将对它的引用存储到可变字段中。 将对它的引用存储到最终字段中。 将对它的引用存储到由(同步)锁适当保护
问题内容: 在《 Java Concurrency In Practice》中,作者指出 不变对象可以通过任何机制发布 不可变对象可以在没有附加同步的情况下被任何线程安全地使用,即使不使用同步来发布它们。 这是否意味着以下成语可以发布不可变对象? 会有数据竞赛吗?(这意味着线程B可能无法在线程A添加的列表中看到不可变对象) 非常感谢你。 此外,作者说,如果Resource是不可变的,以下代码是安全
null 对于此问题的第二部分,将在另一个问题(单击此处)中详细讨论
及其不安全的发布: 可以抛出AssertionError,我同意。作者写道,这是因为不安全的出版,但另一方面没有答案:什么才是正确的出版方式?它们表示了4个安全发布习惯用语,但我不明白,为什么它们会在上面的情况下起作用: 要安全地发布对象,必须同时使对对象的引用和对象的状态对其他线程可见。通过以下方法可以安全地发布构造正确的对象: null 这里是我的第一个问题,谢谢你的帮助!
自我介绍 拷打实习 kafka 介绍你写的最好的接口 设计模式 代理模式 前缀树 为什么不用哈希表 反问: 职责:提供安全平台,平台开发