简体   繁体   English

为什么.Net框架类中的静态方法始终是线程安全的?

[英]Why are static methods in .Net framework classes always thread-safe?

I have noticed the following statement in most places of .Net framework documentation. 我注意到.Net框架文档的大多数地方都有以下声明。

Question : What is the secret to this? 问题 :这个秘诀是什么? I don't think a static class is always thread-safe. 我不认为静态类总是线程安全的。 My question relates to standard classes that are available in .Net framework, and not the custom classes created by developers. 我的问题涉及.Net框架中可用的标准类,而不是开发人员创建的自定义类。

所有.Net Framework类文档中的线程安全说明

Would the method 'GetString' in static class below be thread-safe just because the method is a static method? 下面的静态类中的方法'GetString'是否是线程安全的,因为该方法是一个静态方法?

public static class MyClass
{
    static int x = 0;

    static MyClass()
    {
        x = 23;
    }

    public static string GetString()
    {
        x++;
        return x.ToString();
    }
}

The framework methods you mention are not thread-safe just from the fact they are static, but because they have been specifically designed to be thread-safe. 您提到的框架方法不是线程安全的,因为它们是静态的,但因为它们是专门设计为线程安全的。 Thread-safety is often hard to achieve, but it's usually necessary for static methods, since any state they mutate is shared between threads. 线程安全通常很难实现,但它通常是静态方法所必需的,因为它们变异的任何状态都是在线程之间共享的。

The sample method you posted isn't thread-safe, because it mutates state that is shared between threads, without any synchronization mechanism. 您发布的示例方法不是线程安全的,因为它会改变线程之间共享的状态,而不使用任何同步机制。

The easiest way to use a non-threadsafe instance method without any threading problems is to have that instance only visible to one thread (just don't put a reference to it in a static or anywhere else where a thread other than that which created it is going to access it). 使用非线程安全实例方法而没有任何线程问题的最简单方法是让该实例仅对一个线程可见(只是不要在静态或其他除创建它之外的线程的其他地方放置引用)将要访问它)。 Indeed, this happens more than 90% of the time without any special effort to do so. 实际上,这种情况发生的时间超过90%而没有任何特别的努力。

The second easiest is to associate a lock object with the instance (whether by using it as the lock object, or having a fields for both it and the lock object within the same scope) and making sure all access locks correctly. 第二个最简单的方法是将一个锁定对象与实例相关联(无论是将其用作锁定对象,还是在同一范围内具有该字段和锁定对象的字段)并确保所有访问锁定正确。

With a static method we don't have these option, because there is no such instance and any thread could potentially call either it or another static method that clashes at any time. 使用静态方法我们没有这些选项,因为没有这样的实例,任何线程都可能调用它或其他任何时候发生冲突的静态方法。 It may not even be from code by the same author. 它甚至可能不是来自同一作者的代码。 We also can't guarantee that other code uses the lock object(s) we have in place for use with it. 我们也不能保证其他代码使用我们现有的锁定对象来使用它。

So for this reason a static method that is not threadsafe is of very limited use; 因此,出于这个原因,非线程安全的静态方法的用途非常有限; pretty much only applicable to private static methods used in very limited cases, with these limitations providing the guarantee that it is only called by one thread at a time. 几乎只适用于在非常有限的情况下使用的私有静态方法,这些限制提供了一次只能由一个线程调用的保证。

Hence with all public static methods one would make sure they are threadsafe (or else be very clear in documenting both that they are not threadsafe, and the justification for such a strange thing to do). 因此,使用所有公共静态方法,可以确保它们是线程安全的(或者非常清楚地记录它们不是线程安全的,以及这样一个奇怪事情的理由)。

In fact, you'll find that a great many instance methods documented as "not threadsafe" actually are. 事实上,你会发现许多实例方法记录为“非线程安全”实际上是。 The reasons they're listed as "not threadsafe" are: 他们被列为“非线程安全”的原因是:

  1. If the author hasn't gone to the length of confirming their thread-safety, they'd better not claim what they aren't 100% sure about. 如果作者没有达到确认其线程安全的长度,他们最好不要声称他们不是100%肯定的。
  2. Being wrong in this direction is safe; 朝这个方向走错是安全的; the worse thing that happens is that someone adds their own synchronisation to add thread-safety they didn't need to, which won't actually break anything. 更糟糕的是,有人添加了他们自己的同步来添加他们不需要的线程安全,这实际上不会破坏任何东西。
  3. Since they haven' documented the method as threadsafe they are free to change to a non-threadsafe approach in a later version. 由于他们没有将该方法记录为线程安全,因此可以在以后的版本中自由更改为非线程安全方法。

The specific examples you are referring to are designed to be thread safe. 您所指的具体示例旨在确保线程安全。 That is they allow concurrent access without deadlocks or race conditions. 也就是说,它们允许并发访问而不会出现死锁或竞争条件。

This may not be the case in all instances of all classes, as such Microsoft have chosen to explicitly state which methods are thread safe and which are not to avoid any ambiguity. 在所有类的所有实例中可能不是这种情况,因为Microsoft已选择明确说明哪些方法是线程安全的,哪些方法不避免任何歧义。

See the final paragraph - .NET Class Library 请参阅最后一段 - .NET类库

All public static members (methods, properties, fields, and events) within the .NET Framework support concurrent access within a multithreaded environment. .NET Framework中的所有公共静态成员(方法,属性,字段和事件)都支持多线程环境中的并发访问。 Therefore, any .NET Framework static member can be simultaneously invoked from two threads without encountering race conditions, deadlocks, or crashes. 因此,可以从两个线程同时调用任何.NET Framework静态成员,而不会遇到竞争条件,死锁或崩溃。

For all classes and structures in the .NET Framework, check the Thread Safety section in the API reference documentation to determine whether it is thread safe. 对于.NET Framework中的所有类和结构,请检查API参考文档中的“线程安全”部分,以确定它是否是线程安全的。 If you want to use a class that is not thread-safe in a multithreaded environment, you must wrap an instance of the class with code that supplies the necessary synchronization constructs. 如果要在多线程环境中使用非线程安全的类,则必须使用提供必要同步构造的代码来包装类的实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM