msdn:什么是“线程安全”?

在许多MSDN文档中,这是在Thread Safety标题下编写的;

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

例如; 这里

有人能以一种相当简单的方式解释它吗? 谢谢 :)

Eric Lippert有一篇关于此的精彩博文 。 基本上它本身有点无意义。

就个人而言,当我看到锅炉板时,我在这方面并不太信任MSDN。 它并不总是意味着它所说的。 例如,它说的是关于Encoding的相同的事情 – 尽管我们都使用来自多个线程的编码。

除非我有任何理由不相信(我使用Encoding ),我认为我可以从任何线程调用任何静态成员而不会破坏全局状态。 如果我想从不同的线程使用同一对象的实例成员,我认为如果我确保 – 通过锁定 – 一次只有一个线程将使用该对象,那就没关系。 (当然并非总是这样。有些对象具有线程关联性,并且主动不喜欢从多个线程使用,即使锁定到位.UI控件就是明显的例子。)

当然,如果对象被不明显地共享变得棘手 – 如果我有两个对象,每个对象共享一个对第三个的引用,那么我可能最终使用前两个对象独立于不同的线程,所有正确的锁定 – 但仍然最终破坏第三个对象。

如果一个类型确实宣传自己是线程安全的,我希望它会给出一些关于它的细节。 如果它是不可变的那么很容易 – 你可以只使用你喜欢的实例而不用担心它们。 它是部分或全部“线程安全”类型,在细节非常重要的情况下是可变的。

您可以同时从多个线程访问该类的任何公共静态成员,而不会中断该类的状态。 如果多个线程同时尝试使用实例方法(那些未标记为“静态”的方法)访问该对象,则该对象可能会损坏。

如果尝试同时从多个线程访问该类的同一实例不会导致问题,则该类是“线程安全的”。

一个“线程安全”的对象意味着如果两个线程在同一时间在(或非常接近,在单CPU系统上)使用它,那么它就不会被所述访问破坏。 这通常是通过获取和释放可能导致瓶颈的锁来实现的,因此“线程安全”也可能意味着“缓慢”,如果它不需要的话就完成了。

很多人希望公共静态成员在线程之间共享(注意,VB甚至称之为 “共享”),因此公共静态通常以可以安全使用的方式进行。

实例成员通常不是线程安全的,因为在一般情况下它会降低速度。 因此,如果您有一个想要在线程之间共享的对象,则需要进行自己的同步/锁定。

要理解这一点,请考虑以下示例。 在.net类HashSet的MSDN描述中,有一个部分说明了线程的安全性。 在HashSet类的情况下,MSDN说“这种类型的任何公共静态(在Visual Basic中共享)成员都是线程安全的。 任何实例成员都不能保证是线程安全的。“因为我们都知道竞争条件和死锁的概念,但微软想用简单的英语说什么呢? 如果两个线程将两个值添加到HashSet的“实例”中,则存在一些我们可以将其计数为一的情况。 原因是在这种情况下HashSet对象已损坏,因为我们现在在HashSet中有两个对象,但它的计数只显示一个。 但是,即使两个线程同时添加值,HashSet的公共静态版本也不会面临这样的损坏。