Spring是否以线程安全的方式发布bean? [英] Does Spring publish beans in thread-safe manner?

查看:195
本文介绍了Spring是否以线程安全的方式发布bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My knowledge about JVM internals is that if references are not published correctly, there is a chance that different threads will see different values of the same fields.

我的问题是: Spring bean容器是否保证安全发布?如果没有,我是否应该使所有bean getter和setter synchronized 或使用易失性?或者也许使用 final 字段和构造函数初始化?

My question is: Does Spring beans container guarantee safe publication? If not, should I make all my bean getters and setters synchronized or use volatile? Or maybe use final fields and constructor initialization?

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

I assume that this may only be an issue for singleton beans as prototype beans are created on demand from requesting thread. Is my understanding correct?

推荐答案

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

As Evgeniy has stated, the initialization of an application context happens in a single thread. Therefore the answer to your question isn't so much to do with the internals of Spring but rather the synchronization details between the thread that creates the context and the thread or threads that use the context once it has been created.

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

The Java memory model is based on the happens-before relation (Java Language Specification, §17.4.5) which is defined by various rules. For example, the call to Thread.start made in one thread to start a new thread happens-before all actions in the newly started thread itself. So if your application's main thread first creates an application context, and then starts other threads for processing, then the processing threads are guaranteed to see the fully-initialized context.

字段标记 volatile 还强加发生在之前的关系,因为如果线程A将值写入 volatile ,任何其他看到该写入结果的线程也保证在执行volatile写操作之前看到线程A执行之前的任何其他操作。因此,如果初始化线程和处理线程之间没有任何显式同步,那么以下模式就足以确保安全

Fields marked volatile also impose a happens-before relation, in the sense that if thread A writes a value to a volatile, any other thread that sees the result of that write is also guaranteed to see anything else that thread A did before it did the volatile write. Therefore if there isn't any explicit synchronization between the initialization thread and the processing threads then the following pattern would be sufficient to ensure safety

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
  }
}

这篇关于Spring是否以线程安全的方式发布bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆