是什么使得UnityContainer不是线程安全的陷阱? [英] what are pitfalls of making UnityContainer not thread safe?

查看:156
本文介绍了是什么使得UnityContainer不是线程安全的陷阱?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我添加依赖注入到我的图书馆,我使用统一了点。
和我想知道如果我需要采取一些额外的步骤,使团结集装箱线程安全的。我发现夫妇被谈论的线程安全的容器(例如文章:的 http://www.fascinatedwithsoftware.com/blog/post/2012/01/04/A-Thread-Safe-Global-Unity-Container.aspx ),但如果我真的需要它在我的项目,我不明白。从一个侧面,我不希望有由于来自另一边,我不将发生什么样的情况下的竞争条件看比赛情况有些讨厌的错误。我想用团结与成分根格局和类似的静态构造函数注册所有的类型:

I am adding dependency injection to my library and I use Unity for that. And I am wondering if I need to take some additional steps to make Unity Container thread-safe. I found couple of articles that are talking about Thread-safe container (example: http://www.fascinatedwithsoftware.com/blog/post/2012/01/04/A-Thread-Safe-Global-Unity-Container.aspx ) but I don't understand if I really need it in my project. From one side I don't want to have some nasty bugs due to race conditions from the other side I don't see in what case race condition would occur. I want to use Unity with Composition Root pattern and register all the types in the static constructor like that:

internal static class ConfiguredUnityContainer
    {
        private static readonly UnityContainer Container = new UnityContainer();

        static ConfiguredUnityContainer()
        {
            Container.RegisterType<IConnectionFactory<SqlConnection>>();
        }

        public static T Resolve<T>()
        {
            return Container.Resolve<T>();
        }
    }



所以,基本上我的问题是:在我需要什么样的情况下额外的线程安全的,当我使用Unity DI工作?我在哪里可以得到竞争条件或问题线程安全的?

推荐答案

团结(和所有常见的容器)保证(通过他们的设计师)是线程安全的(或至少,排序的)在并行的情况下,没有注册解析。换句话说,只要你分开的决心阶段报名阶段,从只解决一个点从容器中,你可以叫从多个线程并行解决没有问题。

Unity (and all the common containers) are guaranteed (by their designers) to be thread-safe (or at least, sort of) in case of parallel resolves with no registrations. In other words, as long as you separate the registration phase from the resolve phase, and from one point on only resolve from the container, you can call Resolve in parallel from multiple threads without problems.

作为事实上,作为最佳实践,你应该总是严格分开的决心阶段报名阶段,因为这会导致严重的麻烦,很难找到比赛的条件。

As a matter of fact, as a best practice, you should always strictly separate the registration phase from the resolve phase, because this will lead to serious trouble and very hard to find race conditions.

这些阶段的这种分离是如此的重要,有些DI库(如的 Autofac 简单的注射器)在你强迫这种模式(这里简单的喷油器是严格的两个)。简单注射器文档中包含一个为什么非常明确的解释的情况下,会发生什么简单的注射,迫使你在此模型,并解释你将能够更改配置。引用在这里的解释部分(但你一定要阅读所有的解释):

This separation of those phases is so important, that some DI libraries (such as Autofac and Simple Injector) force this pattern upon you (where Simple Injector is the strictest of the two). The Simple Injector documentation contains a very clear explanation on why Simple Injector forces you upon this model and explains what could happen in case you would be able to change the configuration. To quote part of that explanation here (but you should definitely read the whole explanation):

线程安全问题可以很容易地出现时,用户的Web请求期间更改了
注册。如果容器的请求过程中允许这种
变更登记手续,其他请求能够直接
受到这些变化的影响(因为一般来说应该只有
每个AppDomain一项所述的容器实例)。根据东西,如注册的
生活方式;利用工厂和对象如何
图是结构化的,它可能是一个现实的可能性另一个
要求得到两个一老一新的注册。就拿
被替换为不同的一个瞬态注册。如果
本而不同的线程的对象图正在而服务是
图内注入多点
解析完成 - 图将包含抽象$ B的不同实例$ b在同一时间,同一请求不同的生命周期 - 和
这是不好的。

Problems with thread-safety can easily emerge when the user changes a registration during a web request. If the container allowed such registration changes during a request, other requests could directly be impacted by those changes (since in general there should only be one Container instance per AppDomain). Depending on things such as the lifestyle of the registration; the use of factories and how the object graph is structured, it could be a real possibility that another request gets both the old and the new registration. Take for instance a transient registration that is replaced with a different one. If this is done while an object graph for a different thread is being resolved while the service is injected into multiple points within the graph - the graph would contain different instance of that abstraction with different lifetimes at the same time in the same request - and this is bad.

在我看来,这的文章您链接去多进服务定位器反模式之间的区别和应用依赖注入正确的,这意味着只有访问您的组成的根里面的容器。那篇文章(拉里斯宾塞)的作者是不是很清楚,但他的作文里面的根,他创造了一个单一的统一的容器,并用它为整个应用程序的持续时间。从某种意义上说,它仍然是全球性,但他阻止了例如从通过应用程序被访问(因为那是Service Locator模式)。

As I see it, that the article you are linking goes more into the difference between the Service Locator anti-pattern and applying Dependency Injection correctly, which means only accessing the container inside your Composition Root. The writer of that article (Larry Spencer) isn't very clear, but inside his Composition Root, he creates one single Unity container and uses it for the duration of the whole application. In a sense it is still 'global', but he prevents that instance from being accessed through the application (because that is the Service Locator pattern).

虽然笔者试图创建一个围绕统一容器中的线程安全的包装,他的企图是幼稚的。他所做的是创造周围的每一个注册解析方法的锁。这不仅会给予巨大的拥堵在多线程应用程序,它不解决登记和对象图后更换情况下已经建立和缓存,既简单喷油器的文档时,会发生什么解释的问题,这种统一的 节目的问题。

Although the writer tries to create a thread-safe wrapper around the Unity container, his attempt is naive. What he does is creating a lock around every Register and Resolve method. Not only will this give enormous congestion in multi-threaded applications, it doesn't address the problems of what happens when registering and replacing instances after object graphs have already been build and cached, as both the Simple Injector documentation explains and this Unity question shows.

这篇关于是什么使得UnityContainer不是线程安全的陷阱?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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