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

Spring是否以线程安全的方式发布bean?

仇正平
2023-03-14
问题内容

我对JVM内部的了解是,如果引用未正确发布,则不同的线程有可能看到相同字段的不同值。

我的问题是: Spring beans容器可以保证安全发布吗?
如果没有,我应该使用我所有的豆吸气剂和装塞器synchronized还是使用volatile?还是使用final字段和构造函数初始化?

我认为这可能只是单例bean的问题,因为原型bean是根据请求线程按需创建的。我的理解正确吗?


问题答案:

正如Evgeniy所说,应用程序上下文的初始化发生在单个线程中。因此,您问题的答案与Spring的内部无关,而与创建上下文的线程和创建上下文的线程或使用上下文的线程之间的同步细节有关。

Java内存模型基于由各种规则定义的事前 发生
关系
(Java语言规范,第17.4.5节)。例如,在新启动的线程本身中的所有动作
之前
调用Thread.start一个线程来启动新线程。因此,如果您的应用程序的主线程先创建一个应用程序上下文,然后启动其他线程进行处理,则可以保证处理线程看到完全初始化的上下文。
__

标记的字段volatile还强加了 事前发生的
关系,在某种意义上,如果线程A向a写入一个值volatile,则看到该写入结果的任何其他线程也可以保证看到线程A 执行易失性写入 之前
所做的任何其他操作。因此,如果初始化线程和处理线程之间没有任何显式同步,则以下模式足以确保安全性

public class Setup {
  private volatile boolean inited = false;

  private ApplicationContext ctx;

  public boolean isInited() { return inited; }

  public ApplicationContext getContext() { return ctx; }

  public void init() {
    ctx = new ClassPathXmlApplicationContext("context.xml");
    inited = true; // volatile write
  }
}

public class Processor {
  private void ensureInit() {
    while(!setup.isInited()) { // volatile read
      Thread.sleep(1000);
    }
  }

  public void doStuff() {
    ensureInit();
    // at this point we know the context is fully initialized
  }
}


 类似资料:
  • 我对JVM内部的了解是,如果引用没有正确发布,那么不同的线程有可能看到相同字段的不同值。 我的问题是:Spring beans容器保证安全发布吗?如果不是,我应该让所有bean getter和setter还是使用?或者可能使用字段和构造函数初始化? 我假设这可能只是单例bean的问题,因为原型bean是从请求线程按需创建的。我的理解正确吗?

  • 下面我分享了我的代码,我试图使用线程安全的Nashorn作为脚本引擎来评估简单的数学公式。公式将类似于“a*b/2”,其中a 我需要知道这种方法是否有助于使Nashorn线程在这个用例中安全。我在Attila的回答中读到,我们可以在线程之间共享脚本引擎对象,因为它们是线程安全的。 对于bindings和eval,因为我们正在为每次执行evaluate创建新线程,每个线程都有自己的bindings对

  • 问题内容: 阅读“实践中的Java并发性”,第3.5节包含以下内容: 除了创建两个的明显的线程安全隐患外,该书还声称可能会发生发布问题。 此外,对于诸如 一个可以扔! 这怎么可能?我能想到的唯一允许这种荒谬行为的方法是,如果构造函数不被阻塞,那么当构造函数代码仍在另一个线程中运行时,将创建对实例的引用。 这可能吗? 问题答案: 之所以可行,是因为Java的内存模型较弱。它不保证读写顺序。 可以通过

  • 问题内容: 我一直在假设线程安全也不是线程安全,但是在最近的一次讨论中,一位同事告诉我线程安全。 因此,我做了一些研究,却一无所获。很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档没有以一种或另一种方式说任何话,不是为了,甚至不是。 那是什么呢? 问题答案: 这是指向Java 7 中Calendar和GregorianCalendar的源代码的链接。 如果阅读该代码,您

  • 问题内容: 我有多个线程试图更新MySQL数据库?使用executeUpdate方法是线程安全的吗? 问题答案: 不,使用它不是线程安全的。 实际上,如果其他某个线程使用一条语句,然后另一个线程调用executeUpdate(),则另一个线程的s(如果有的话)将被关闭。“ javadoc.sql.Statement的JavaDoc(PreparedStatement是其子类型) ”如果存在打开的语

  • 我在几个地方读到过SimpleDateFormat不是线程安全的,但是线程是一个对我来说仍然不清楚的概念,所以我想知道下面的代码是不是线程安全的; 这是一个驻留在名为“dateutils.java”的类中的方法,在我正在处理的Spring Boot应用程序中,我使用访问它,只要我需要将字符串转换为日期(如果转换失败,则将异常传递给控制器)。 由于这个方法在每次调用时都使用SimpleDateFor