Spring 对象线程安全吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15745140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:50:21  来源:igfitidea点击:

Are Spring objects thread safe?

spring

提问by Sathesh

Are Spring objects thread safe? If not, how to make them thread safe?

Spring 对象线程安全吗?如果没有,如何使它们线程安全?

回答by tolitius

These are two unrelated questions:

这是两个不相关的问题:

Are Spring Beans Thread Safe?

Spring Beans 线程安全吗?

No.

不。

Spring has different bean scopes(e.g. Prototype, Singleton, etc.) but all these scopes enforce is whenthe bean is created. For example a "prototype" scoped bean will be created each time this bean is "injected", whereas a "singleton" scoped bean will be created once and shared within the application context. There are other scopes but they just define a time span (e.g. a "scope") of whena new instance will be created.

Spring 有不同的 bean作用域(例如 Prototype、Singleton 等),但所有这些作用域都是创建 bean强制执行的。例如,每次“注入”这个 bean 时,都会创建一个“原型”作用域 bean,而将创建一次“单个”作用域 bean,并在应用程序上下文中共享。还有其他范围,但它们只是定义了何时创建新实例的时间跨度(例如“范围”)。

The above has little, if anything to do with being thread safe, since if several threads have access to a bean (no matter the scope), it would only depend on the designof that bean to be or not to be "thread safe".

上面的内容与线程安全几乎没有关系,因为如果多个线程可以访问一个 bean(无论范围如何),则只取决于该 bean的设计是否“线程安全” .

The reason I said "little, if anything" is because it might depend on the problem you are trying to solve. For example if you are concerned whether 2 or more HTTP requests may create a problem for the same bean, there is a "request" scopethat will create a new instance of a bean for each HTTP request, hence you can "think" of a particular bean as being "safe" in the context of multiple HTTP requests. But it is still not truly thread safe by Springsince if several threads use this bean within the sameHTTP request, it goes back to a bean design (yourdesign of a bean backing class).

我之所以说“很少,如果有的话”是因为这可能取决于您要解决的问题。例如,如果您担心 2 个或更多 HTTP 请求是否会为同一个 bean 造成问题,则有一个“请求”范围将为每个 HTTP 请求创建一个 bean 的新实例,因此您可以“考虑”一个特定 bean 在多个 HTTP 请求的上下文中是“安全的”。但是它仍然不是Spring真正线程安全的因为如果多个线程在同一个HTTP 请求中使用这个 bean ,它会回到 bean 设计(的 bean 支持类的设计)。

How to Make/Design a Thread Safe "Object"?

如何制作/设计线程安全的“对象”?

There are several ways, probably too long to list here but here are a few examples:

有几种方法,可能太长无法在此列出,但这里有一些示例:

  • Design your beans immutable: for example have no setters and only use constructor arguments to create a bean. There are other ways, such as Builder pattern, etc..

  • Design your beans stateless: for example a bean that doessomething can be just a function (or several). This bean in most cases can and shouldbe stateless, which means it does not have any state, it only doesthings with function arguments you provide each time (on each invocation)

  • Design your beans persistent: which is a special case of "immutable", but has some very nice properties. Usually is used in functional programming, where Spring (at least yet) not as useful as in imperative world, but I have used them with Scala/Spring projects.

  • Design your beans with locks [last resort]: I would recommend against this unless you are working on a lowerlevel library. The reason is we (humans) are not good thinking in terms of locks. Just the way we are raised and nurtured. Everything happens in parallel without us needing to "put that rain on pause, let me get an umbrella". Computers however are all about locks when you are talking "multiple things at the same time", hence there are some of us (exceptional people) who are doing their fair share and implementing libraries based on these locks. Most of other humans can just usethese libraries and worry not about concurrency.

  • 设计你的 bean不可变:例如没有 setter 并且只使用构造函数参数来创建 bean。还有其他方式,比如Builder模式等。

  • 设计您豆类无状态:比如一个bean是什么可以只是一个函数(或几个)。这个bean在大多数情况下可以和应该是无状态的,这意味着它没有任何状态下,只有确实与函数参数的东西,你每次提供(在每次调用)

  • 设计您的 bean持久性:这是“不可变”的特例,但具有一些非常好的属性。通常用于函数式编程,其中 Spring(至少目前)不如在命令式世界中有用,但我已经将它们用于 Scala/Spring 项目。

  • 用锁设计你的 bean [最后的手段]:除非你在一个较低级别的库上工作,否则我建议不要这样做。原因是我们(人类)在锁方面没有很好的思考。就像我们被抚养和培养的方式一样。一切都是并行发生的,我们不需要“让雨停下来,让我拿把伞”。然而,当你在谈论“同时进行多件事”时,计算机都是关于锁的,因此我们中的一些人(特殊的人)正在公平地分享并实现基于这些锁的库。大多数其他人可以只使用这些库而不必担心并发性。

回答by artfulbeest

Spring does not guarantee thread safety. But it provides guidelines on the matter. If your beans have state do not use singleton bean scope.

Spring 不保证线程安全。但它提供了有关此事的指导方针。如果您的 bean 有状态,请不要使用单例 bean 范围。

I created a demo to show the mutability of spring beans with Singleton and Prototype scope

我创建了一个演示来展示具有 Singleton 和 Prototype 范围的 spring bean 的可变性

I focused on stateful beans, then used Singleton and Prototype scopes to show how the beans mutate their state.

我专注于有状态的 bean,然后使用 Singleton 和 Prototype 作用域来展示 bean 如何改变它们的状态。

The class Job is extended by JobPrototype and JobSingleton beans which are loaded based on the active profile set. Tp set profile, set the property spring.profiles.active to either proto (for prototype scope) or singleton (for Singleton scope)

Job 类由 JobPrototype 和 JobSingleton bean 扩展,它们基于活动配置文件集加载。tp 设置配置文件,将属性 spring.profiles.active 设置为 proto(对于原型范围)或单例(对于单例范围)

The active job beans are autowired inside Runner and Runner1 beans which have Scheduled methods to mutate state of the autowired bean periodically

活动作业 bean 在 Runner 和 Runner1 bean 中自动装配,它们具有 Scheduled 方法来定期改变自动装配 bean 的状态

public class Job {

protected int count = 0;

void counter() {
    this.count++;
}

public int getCount() {
    return count;
}

}

}

@Component
@Profile("proto")
@Scope("prototype")
public class JobPrototype extends Job {
}

@Component
@Profile("singleton")
public class JobSingleton extends Job {

}

@Component
public class Runner {

    private Logger Log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private Job job;

    @Scheduled(fixedDelay = 1500)
    void count() {
        this.job.counter();
        Log.info("### Runner: count: " + this.job.getCount());
    }
}

@Component
public class Runner1 {

    private Logger Log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private Job job;

    @Scheduled(fixedDelay = 1000)
    void count() {
        this.job.counter();
        Log.info("### RunnerOne: count: " + this.job.getCount());
    }

}

The results are

结果是

  1. Singleton Singleton Scope

  2. Prototype Prototype Scope

  1. 例作用域

  2. 原型 原型范围

Full code for this demo beans_mutability

此演示beans_mutability 的完整代码