代码之家  ›  专栏  ›  技术社区  ›  H2ONaCl

.NET线程安全

  •  8
  • H2ONaCl  · 技术社区  · 16 年前

    列表。添加是实例成员。这意味着它不能保证线程安全。这是什么意思?

    可能性1。如果两个线程在不同的实例上调用.Add,根据月球的相位,可能会出现意外的结果?

    可能性2。如果两个线程在同一个实例上调用.Add,可能会出现意外的结果,这取决于月球的相位,如果实例不同,则没有潜在的问题。

    可能性3。微软根本不希望人们使用线程,所以他们写的.NET是模棱两可的。

    5 回复  |  直到 12 年前
        1
  •  10
  •   Jon Hanna    16 年前

    可能性1并非如此。一个实例方法会给其他实例带来问题,这是非常不寻常的,因此应该清楚地记录下来(不仅要有一个声明指出这一点,还要有一些理由,因为这通常是非常糟糕的编码的标志,所以如果有一个很好的理由,就会指出这一点)。

    可能性3不是这样,因为他们刚刚记录了线程行为。

    1. 如果静态方法不是线程安全的,那么以线程安全的方式调用该方法是非常困难的,特别是如果该类可能由不同的人编写的不同代码层使用。这使得使这些方法线程安全的努力几乎总是合理的。大多数这样的成员也相对容易使线程安全(如果一个成员避免了可变的静态,这总是一件好事情要避免)。

    2. 相当地 对于使用该类的人员来说,确保多线程使用的实例以线程安全的方式使用是很容易的。

    这里非常强调“相对的”,因为编写线程安全代码并不总是那么容易。有时它相当简单(不可变类需要一些工作才能使非线程安全!),但更多的时候,这是非常困难的(因此许多问题的主题在这里和其他地方)。

    然而,这正是为什么在这种情况下,负担应该放在用户身上。使这样一个类完全线程安全是如此困难(事实上,有时证明是不可能的),以至于结果对于大多数用户来说是不可接受的,他们是最有能力判断在给定的情况下需要什么样的保护的人。

        2
  •  4
  •   Femaref    16 年前

    我想, List.Add 是个坏例子。 List.Remove 更好,因为实际上有值得注意的线程问题。一个线程可以尝试访问一个项目,而另一个线程将尝试调用 在上面。现在,有可能在试图访问该项时将其删除,从而导致 NullReferenceException . 一般来说,这是一个免责声明,但要知道,因为没有锁定机制到位。只要记住 lock

        3
  •  0
  •   user195488 user195488    16 年前

    因为没有在实例成员上实现锁定机制,所以他们将该免责声明放在MSDN网站上。

    另请参见 Statics and Thread Safety

    Statics and Thread Safety: Part II

        4
  •  0
  •   supercat    16 年前

    如果两个线程同时尝试对同一个列表实例执行不同的操作,则可能会发生不好的事情。多个线程同时使用一个列表做不同的事情是安全的,唯一的情况是所有线程都在读取。我认为使用列表是安全的,尽管使用所有容器类也未必安全。

        5
  •  0
  •   cHao    16 年前

    如果两个不同的线程在没有同步/锁定的情况下修改同一个列表,则可能会导致问题。两个线程处理不同的列表就可以了。大多数类也是如此——实际上,只有非常少的类显式地声明“这个类是线程安全的”,但是如果不在线程之间共享(访问)实例,那么几乎所有的类都是安全的。如果一个类在线程不共享实例的情况下甚至出现中断,文档会这么说——但这是一个非常糟糕的情况,我希望微软能将它排除在API之外。

    微软的言行方式(线程安全方面)有一个巨大的原因:

    线程安全是困难的。

    没有办法同步对每个人都有用的东西。在不需要的情况下锁定和同步可能会破坏性能甚至稳定性。全面的最佳解决方案是让代码只做它应该做的事情,sans同步,让需要线程安全的人自己安排。

    推荐文章