【问题标题】:Safe publication through final通过最终安全发布
【发布时间】:2010-10-20 02:39:47
【问题描述】:

即使经过this,我仍然不清楚 final 的使用如何导致以下代码中的安全发布。谁能给个通俗易懂的解释。

public class SafeListener
{
    private final EventListener listener;

    private SafeListener()
    { 
         listener = new EventListener()
         {  public void onEvent(Event e)
            {  doSomething(e); }
          };
    }

    public static SafeListener newInstance(EventSource source)
    {    
          SafeListener safe = new SafeListener(); 
          source.registerListener(safe.listener);
          return safe;
    }
}

【问题讨论】:

    标签: java


    【解决方案1】:

    编辑添加:origins of Java and JSR-133's final behavior 的有趣观点。

    final 如何在新 JMM 中工作的规范参考,以确保安全发布:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight

    简单回顾一下,我认为您的代码代表了对EventSource source 对象的“安全”发布,这可能会在不同的线程中处理对listener 的事件回调。您可以保证在传递的safe.listener 引用上运行的线程将看到完全初始化的listener 字段。这进一步保证与调用 onEvent 或与对象状态的其他交互相关的其他同步问题。

    您的代码保证的是,当SafeListener 的构造函数在静态方法内返回引用时,listener 字段将不会以未写入的状态出现(即使没有显式同步)。例如:假设线程 A 调用newInstance(),导致分配给listener 字段。假设线程 B 能够取消引用 listener 字段。然后,即使没有任何其他同步,线程 B 也可以保证看到写入 listener = new EventListener()...。如果该字段不是final,您将不会收到该保证。有几种(其他)方法可以保证不同的性能和可读性(显式同步、使用原子引用、使用 volatile)。

    并非所有合法的东西都是可取的。建议你看看JCiP,也许看看这个article on safe publication techniques

    这里有一个最近的相关问题:"Memory barriers and coding...""Java multi-threading & Safe Publication"

    【讨论】:

    • @iJeeves:很高兴这样做,但如果你举一些例子来说明你的发布是什么意思会有所帮助——你打算如何让客户端代码使用SafeListener,特别是,访问listener 字段?还有其他同步限制吗?
    • @iJeeves:没关系,你的代码足够了,我看错了。修改了我的答案。
    【解决方案2】:

    简而言之,final 的规范(请参阅 @andersoj 的回答)保证当构造函数返回时,最终字段将被正确初始化(从所有线程可见)。

    对于非最终字段没有这样的保证(这意味着如果另一个线程获取了新构造的对象,则该字段可能尚未设置)。

    这是 JVM 规范的一部分。

    它是如何工作的将是一个 JVM 实现细节。

    【讨论】:

      【解决方案3】:

      可以参考JSL 最终字段或可通过最终引用访问的对象无法使用对该对象的引用的初始加载重新排序。它在构造后对所有其他线程可见。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 1970-01-01
        相关资源
        最近更新 更多