C# 静态方法线程安全吗

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1090650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:59:40  来源:igfitidea点击:

Are static methods thread safe

c#asp.netstatic

提问by

I have a static timer class which will be called by ANY webpage to calculate how long each page has taken to be constructed.

我有一个静态计时器类,任何网页都会调用它来计算每个页面的构建时间。

My question is are Static classes thread safe? In my example will concurrent users cause a problem with my start and stop times? e.g a different threads overwriting my start and stop values.

我的问题是静态类线程安全吗?在我的示例中,并发用户是否会导致我的开始和停止时间出现问题?例如,不同的线程覆盖了我的开始和停止值。

public static class Timer
{
    private static DateTime _startTime;
    private static DateTime _stopTime;    

    /// <summary>
    /// Gets the amount of time taken in milliseconds
    /// </summary>
    /// <returns></returns>
    public static decimal Duration()
    {
        TimeSpan duration =  _stopTime - _startTime;
        return duration.Milliseconds;
    }

    public static void Start()
    {
        _startTime = DateTime.Now;
    }

    public static void Stop()
    {
        _stopTime = DateTime.Now;
    }
}

Should this class be a non-static class?

这个类应该是非静态类吗?

(This class will called from the asp.net masterpage.)

(这个类将从 asp.net 母版页调用。)

采纳答案by Jon Skeet

Static methods aren't inherentlythread-safe. They're treated no differently by the CLR than instance methods. The difference is that one should generally try to makethem thread-safe. (I can't think of any .NET BCL static methods which aren't thread-safe.) Instance methods are often not thread-safe because the typical pattern is to create an object and use it repeatedly from one thread, and if it doeshave to be used from multiple threads, the co-ordination involved includes making sure that the object is used safely. In very many cases that's more appropriate to do in the co-ordinating code than in the object itself. (Usually you want to make whole sequences of operations effectively atomic - something which can't be done within the object.)

静态方法本质上不是线程安全的。CLR 对它们的处理与实例方法没有区别。不同之处在于通常应该尝试使它们成为线程安全的。(我想不出任何不是线程安全的 .NET BCL 静态方法。)实例方法通常不是线程安全的,因为典型的模式是创建一个对象并从一个线程重复使用它,如果它确实必须从多个线程中使用,所涉及的协调包括确保安全使用对象。在很多情况下,这在协调代码中比在对象本身中更合适。(通常你想让整个操作序列有效地原子化——这是在对象中无法完成的。)

Your Timerclass is most definitely not thread-safe: two threads can stomp on each other's data with ease, and there's nothing to stop a thread from using "stale" data when calculating the duration.

您的Timer类绝对不是线程安全的:两个线程可以轻松地践踏彼此的数据,并且在计算持续时间时没有什么可以阻止线程使用“陈旧”数据。

Use the Stopwatchclass instead - that's what it's there for. Admittedly if you want to use one instance from multiple threads you'll need to take the normal steps to ensure safety, but you'll be in a much better position in general. Admittedly Stopwatchis far from perfect too - see this questionand the comment below for more details - but it is at least what the type is designed for. (Who knows, it may be fixed some time...)

改用Stopwatch该类 - 这就是它的用途。诚然,如果您想使用来自多个线程的一个实例,您需要采取正常步骤来确保安全,但总的来说,您会处于一个更好的位置。不可否认,它Stopwatch也远非完美 - 请参阅此问题和下面的评论以获取更多详细信息 - 但这至少是该类型的设计目的。(谁知道呢,它可能会在一段时间内修复......)

回答by Tom

Yes, you're right, the static members / accessors on this class will cause them to be overwritten by different users.

是的,你是对的,这个类上的静态成员/访问器会导致它们被不同的用户覆盖。

This is why you have instances and non-static members.

这就是您拥有实例和非静态成员的原因。

回答by Philippe Leybaert

Your timer class is definitely not thread-safe. You should create a normal class and instantiate it every time you need to measure the time:

您的计时器类绝对不是线程安全的。您应该创建一个普通类并在每次需要测量时间时实例化它:

Timer timer = new Timer();

timer.Start();
//...
timer.Stop();

decimal duration = timer.Duration();

Better still, there is a built-in .NET class that does exactly that:

更好的是,有一个内置的 .NET 类可以做到这一点:

Stopwatch sw = Stopwatch.StartNew();

sw.Stop();

TimeSpan duration = sw.Elapsed;

回答by Bill

There is a good discussion herethat focuses more on the mechanisms and reasons for why your example is not thread-safe.

这是一个很好的讨论在这里是更侧重于机制和原因,为什么你的例子不是线程安全的。

To summarize, first, your static variables will be shared. If you could make them local variables, even though they are local to a static method, they would still get their own stack frame, and thus, be thread-safe. Also, if you otherwise protect your static variables (ie, locks and/or other multi-threaded programming techniques mentioned by others in this thread) you could also make your sample static class thread-safe.

总而言之,首先,您的静态变量将被共享。如果您可以使它们成为局部变量,即使它们是静态方法的局部变量,它们仍将获得自己的堆栈帧,因此是线程安全的。此外,如果您以其他方式保护您的静态变量(即,该线程中其他人提到的锁和/或其他多线程编程技术),您还可以使您的示例静态类线程安全。

Second, because your example does not take in external variable instances which you modify or whose state might get acted upon by another thread, your example is thread-safe in that regard as well.

其次,因为您的示例不接受您修改的外部变量实例或其状态可能会被另一个线程处理,所以您的示例在这方面也是线程安全的。