gpt4 book ai didi

c# - 使 UnityContainer 不是线程安全的陷阱是什么?

转载 作者:太空狗 更新时间:2023-10-29 22:18:49 24 4
gpt4 key购买 nike

我正在向我的库中添加依赖项注入(inject),为此我使用了 Unity。我想知道我是否需要采取一些额外的步骤来使 Unity Container 线程安全。我找到了几篇讨论线程安全容器的文章(例如:http://www.fascinatedwithsoftware.com/blog/post/2012/01/04/A-Thread-Safe-Global-Unity-Container.aspx),但我不明白我的项目是否真的需要它。一方面,我不想因为竞争条件而出现一些讨厌的错误,另一方面,我看不到竞争条件会在什么情况下发生。我想将 Unity 与 Composition Root 模式一起使用,并像这样在静态构造函数中注册所有类型:

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(以及所有通用容器)(由它们的设计者)保证在没有注册的情况下是线程安全的(或者至少, sort of )。换句话说,只要您将注册阶段与解析阶段分开,并且从一个点开始只从容器解析,您就可以从多个线程并行调用 Resolve 而不会出现问题。

事实上,作为最佳实践,您应该始终将注册阶段与解析阶段严格分开,因为这会导致严重的麻烦并且很难找到竞争条件。

这些阶段的分离非常重要,以至于某些 DI 库(例如 AutofacSimple Injector )将这种模式强加给您(其中 Simple Injector 是两者中最严格的)。 Simple Injector 文档包含一个 very clear explanation,说明 Simple Injector 为何强制您使用此模型,并解释了如果您能够更改配置会发生什么情况。在这里引用部分解释(但你绝对应该阅读整个解释):

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.

如我所见,您链接的 the article 更多地体现了 Service Locator anti-pattern 与正确应用依赖注入(inject)之间的区别,这意味着仅访问 Composition Root 内的容器。那篇文章的作者 (Larry Spencer) 不是很清楚,但在他的 Composition Root 中,他创建了一个单一的 Unity 容器,并在整个应用程序的持续时间内使用它。从某种意义上说,它仍然是“全局的”,但他阻止了通过应用程序访问该实例(因为那是服务定位器模式)。

虽然作者试图围绕 Unity 容器创建一个线程安全的包装器,但他的尝试是幼稚的。他所做的是在每个 RegisterResolve 方法周围创建一个锁。这不仅会在多线程应用程序中造成巨大的拥塞,而且不会解决在对象图已经构建和缓存后注册和替换实例时发生的问题,正如 Simple Injector 文档和 Unity question 所解释的那样.

关于c# - 使 UnityContainer 不是线程安全的陷阱是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30491385/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com