可以接受锁定(AppDomain.CurrentDomain)吗?
我想使用 AppDomain.CurrentDomain.GetAssemblies() 枚举 Asp.NET 应用程序中所有已加载的程序集。然而,在检查AppDomain的文档时,我发现以下声明:
线程安全
此类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。
由于 GetAssemblies()
是一个实例方法,我认为这是因为我必须在该调用周围采取某种锁定,如果不是为了其他目的,以防止其他人将新程序集加载到域,同时我正在枚举当前的域。我希望 AppDomain 提供某种 SyncRoot 属性,但它没有,而且我没有在网上找到任何有关如何操作的信息。
我该如何同步此呼叫?
编辑
- 我知道lock语句用于创建合作锁,这正是我想以其他人所做(或应该做)的方式锁定AppDomain的原因,而不是创建我自己的锁不会阻止不属于我的代码在我枚举程序集时加载程序集。
- 我知道任何人都可以获取的锁通常是一个坏主意,但我也知道在执行不安全操作时不获取锁更糟糕。
- 到目前为止,两个答案都表明 GetAssemblies() 实际上是线程安全的。这对我来说是有道理的,我真的希望情况如此,但你怎么知道呢?有没有人有参考文献来支持这一说法?我的 google-fu 失败了,Reflector 显示该方法是内部本机方法的薄包装。
I want to enumerate all loaded assemblies in an Asp.NET application, using AppDomain.CurrentDomain.GetAssemblies()
. However, when checking the documentation for AppDomain, I find the following statement:
Thread Safety
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Since GetAssemblies()
is an instance method, I take this as I have to make take some kind of lock around that call, if not for anything else so to prevent anyone else from loading a new assembly into the domain while I'm enumerating the current ones. I would expect AppDomain to provide some kind of SyncRoot property, but it doesn't, and I have not found any information on the web about how to do.
How am I supposed to synchronize this call?
Edit
- I know that the lock statement is used to create a cooperative lock, this is exactly the reason that I want to lock the AppDomain in the same way everyone else does (or should do), rather than create my own lock that won't prevent code that's not mine from loading assemblies while I'm enumerating them.
- I know that locks that can be taken by anyone are usually a bad idea, but I also know that not taking a lock when performing unsafe operations is even worse.
- Both answers so far say that GetAssemblies() is, in fact, thread-safe. This makes sense to me, and I would really expect it to be the case, but how do you know it? Does anyone have a reference to support this claim? My google-fu has failed me and Reflector shows that this method is a thin wrapper around an internal native method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一般来说,SyncRoot 属性是一个非常糟糕的主意。原因之一是两个独立开发的库可能会在不知不觉中决定锁定共享的 SyncRoot 属性,并很快在应用程序中引入死锁。锁定是一种无法在两个独立组件之间轻松可靠地共享的操作。这里最好的策略是开发您自己的锁,供您的组件使用来同步访问。
在这种情况下,尽管从多个线程调用 GetAssemblies 是安全的,因此不需要锁定。您看到的警告是添加到 BCL 中每个类的一般语句,除非作者专门为线程安全设计了该类型并删除了该消息。
SyncRoot properties in general are a very bad idea. One reason why is it's possible for 2 independently developed libraries to unknowingly decide to lock against a shared SyncRoot property and quickly introduce deadlocks into the application. Locking is an operation that cannot easily be reliably shared between two independent components. The best strategy here is to develop your own lock which is used by your components to synchronize access.
In this case though calling GetAssemblies is safe to do from multiple threads so no locking is needed. The warning you see is a general statement added to every class in the BCL unless the author specifically designed the type for thread safety and removed the message.
这是标准的免责声明;你不需要担心它。
一般来说,只要您(或另一个线程)不修改对象,就可以从多个线程调用实例方法。
请注意,您永远不应该锁定 AppDomain 对象。
That is a standard disclaimer; you don't need to worry about it.
In general, as long as you (or another thread) do not modify the object, instance methods can be called from multiple threads.
Note that you should never lock on an AppDomain object.