当前位置: 首页 > 面试题库 >

最终安全发布

潘高洁
2023-03-14
问题内容

即使经过了这一点,我仍然不清楚在以下代码中使用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和JSR-133
final行为起源的
有趣观点。

有关如何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看到write
listener = new EventListener()...。如果该字段不是final,您将不会获得该保证。有几种(其他)方式可提供不同性能和可读性的保证(显式同步,原子引用的使用,易失性的使用)。

并非所有合法的建议都是可取的。建议您看一下JCiP以及有关安全发布技术的这篇文章。



 类似资料:
  • 每个方法将一个排入队列,以便在另一个线程上执行。在后台线程上调用来执行某些任务,在UI线程上调用来显示结果。 如果我们假设返回一个可变的、未同步的列表,例如ArrayList,那么赋值给的最后一个参数是否可以确保列表的安全发布,还是需要采取额外的步骤来确保安全发布?

  • 问题内容: 为了线程安全,是否应该是故意不可变的Java类’final’的所有字段(包括超字段),还是没有修饰符方法就足够了? 假设我有一个带有非最终字段的POJO,其中所有字段都是某种不可变类的类型。这个POJO有getters- setters和一个设置一些初始值的构造函数。如果我通过敲除修饰符方法来扩展此POJO,从而使其不可变,那么扩展类是否是线程安全的? 问题答案: 为了以线程安全的方式

  • 问题内容: 从实践中的Java并发性书中: 为了安全地发布对象,必须同时使对该对象的引用和该对象的状态对其他线程可见。可以通过以下方式安全地发布正确构造的对象: 从静态初始化程序初始化对象引用 将对它的引用存储到volatile字段或AtomicReference中 将对其的引用存储到正确构造的对象的最终字段中 将对它的引用存储到由 锁适当保护的字段中。 我的问题是: 项目符号点2和3之间有什么区

  • 问题内容: 我试图简单地测试JLS保证的最终字段的初始化安全性。这是我写的论文。但是,根据我当前的代码,我无法使其失败。有人可以告诉我我做错了什么吗,或者这只是我必须一遍又一遍然后看到失败的时机而已? 这是我的代码: 我的线程正在这样调用它: 我已经多次运行过这种情况。我当前的循环产生了10,000个线程,但是我已经完成了1000、100000,甚至一百万个线程。仍然没有失败。我总是看到3和4这两

  • 问题内容: 我已经阅读了很多,但是还没有找到确切的答案。 我有一堂课,看起来像这样: 而且我想知道从Foo实例访问sharedData是否是线程安全的(如构造函数和doSomethingUseful()中所示)。Foo的许多实例将在多线程环境中创建。 我的意图是在静态初始化程序中初始化sharedData,此后不进行修改(只读)。 我读到的是,不可变对象本质上是线程安全的。但是我仅在实例变量的上下

  • 问题内容: 从我有很多的用户输入和…此刻我总是写.. 我想知道您是否可以创建一个可以立即保护,转义和清理/ 数组的函数,因此您不必在每次使用用户输入等时都进行处理。 我在想一个功能,例如,和它里面,它应该做的,,,(我想这是所有做它的清洁与安全),然后返回。 那有可能吗?制作一个适用于和的函数,因此您只需执行以下操作: 因此,在以后的代码中,当您使用eg 或时,它们是否已固定,剥离等? 试了一下自