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

Mar*_*cin 15 java spring multithreading

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

我的问题是:Spring bean容器能保证安全发布吗?如果没有,我应该制作所有的bean吸气剂和制定者synchronized还是使用volatile?或者也许使用final字段和构造函数初始化?

我认为这可能只是单例bean的一个问题,因为原型bean是根据请求线程创建的.我的理解是否正确?

Ian*_*rts 10

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

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

标记的字段volatile还强加了一个before-before关系,在某种意义上,如果线程A将值写入a volatile,则任何其他看到该写入结果的线程也可以保证执行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
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是对JMM的非常好而正确的解释。但是它不能回答OP的问题:Spring bean容器可以保证安全发布吗? (3认同)