【问题标题】:Acceptable to lock (AppDomain.CurrentDomain)?可以锁定 (AppDomain.CurrentDomain) 吗?
【发布时间】:2010-02-24 16:38:52
【问题描述】:

我想使用AppDomain.CurrentDomain.GetAssemblies() 枚举Asp.NET 应用程序中所有加载的程序集。但是,在查看 AppDomain 的文档时,我发现以下语句:

线程安全

此类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。

由于GetAssemblies() 是一个实例方法,我接受它是因为我必须对该调用进行某种锁定,如果不是为了其他任何东西,以防止其他人在我将新程序集加载到域中时m 枚举当前的。我希望 AppDomain 提供某种 SyncRoot 属性,但它没有,而且我没有在网上找到任何关于如何做的信息。

我应该如何同步这个调用?

编辑

  1. 我知道 lock 语句是用来创建合作锁的,这正是我想以与其他人一样(或应该做)的方式锁定 AppDomain 的原因,而不是创建自己的锁'在我枚举它们时,不要阻止不是我的代码加载程序集。
  2. 我知道任何人都可以使用的锁通常是个坏主意,但我也知道在执行不安全的操作时不使用锁会更糟糕。
  3. 到目前为止,两个答案都说 GetAssemblies() 实际上是线程安全的。这对我来说是有道理的,我真的希望会是这样,但你怎么知道呢?有没有人可以参考支持这一说法?我的 google-fu 让我失望了,Reflector 显示此方法是内部原生方法的薄包装。

【问题讨论】:

  • 注意:lock 关键字不会“锁定对象”,因此其他代码无法使用它。相反,它保证任何其他尝试获取同一对象上的锁的代码都必须等到所有其他锁(当前和之前的锁)都被释放。换句话说,“除了我没有人使用这个”场景只有在对象只在锁块内使用时才是现实的。如果任何代码在没有获得锁的情况下使用它,这些语义就会失败。
  • 我确切地知道 lock 关键字的作用,而且我也知道您几乎不应该锁定公共对象。
  • 但是,我也知道竞态条件是最难调试的问题之一,所以我最想避免它们。

标签: .net synchronization appdomain


【解决方案1】:

SyncRoot 属性通常是一个非常糟糕的主意。 2 个独立开发的库可能在不知不觉中决定锁定共享的 SyncRoot 属性并迅速将死锁引入应用程序的原因之一。锁定是一种无法在两个独立组件之间轻松可靠共享的操作。这里最好的策略是开发你自己的锁,你的组件使用它来同步访问。

在这种情况下,尽管从多个线程调用 GetAssemblies 是安全的,因此不需要锁定。您看到的警告是添加到 BCL 中每个类的一般语句,除非作者专门为线程安全设计了类型并删除了该消息。

【讨论】:

  • 我怎样才能看到它是安全的?它没有被记录为对该方法安全,并且 AppDomain 类被记录为不是线程安全的。 Assembly 类 OTOH 被记录为线程安全的。
  • 顺便说一句,SyncRoot 不是一个坏主意。坏主意是拥有如此共享的状态,以至于您永远不知道谁在使用它。但是,当这种情况发生时,AppDomain 就是这种情况(有充分的理由),最好有一个 SyncRoot 而不是没有它,因为没有一个明确定义的对象来锁定你就不可能防止竞争条件。
【解决方案2】:

这是标准的免责声明;您无需担心。
一般来说,只要你(或其他线程)不修改对象,就可以从多个线程调用实例方法。

注意you should never lock on an AppDomain object

【讨论】:

  • 此外,您永远不应该锁定您不拥有的任何东西。如果你没有创建 AppDomain 对象,你应该小心锁定它。
  • 我在哪里可以看到它是一个标准的免责声明并且不特别关注这种方法?相反,在 Assembly 类的文档中,您可以阅读“这种类型是线程安全的”。我的问题是我不知道其他人是否修改了对象,因为另一个同时请求可能(直接或间接)调用 Assembly.Load,这无疑会修改已加载程序集的列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多