静态方法是线程安全的
我有一个静态计时器类将被任何网页调用来计算每个页面已经被构造了多长时间。
我的问题是静态类线程安全吗? 在我的例子中,并发用户会导致我的开始和结束时间有问题吗? 例如不同的线程覆盖我的开始和结束值。
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; } }
这个类应该是一个非静态类吗?
(这个类将从asp.net masterpage中调用。)
静态方法本质上不是线程安全的。 与实例方法相比,它们对CLR的处理方式不同。 不同的是,一般应该尽量使它们线程安全。 (我想不出任何.NET BCL静态方法是不是线程安全的。)实例方法通常不是线程安全的,因为典型的模式是创build一个对象,并从一个线程重复使用它,如果它必须从多个线程中使用,所涉及的协调包括确保对象被安全地使用。 在很多情况下,在协调代码中比在对象本身中更合适。 (通常你想要使整个操作序列有效地为primefaces – 在对象内不能完成的事情。)
您的Timer
类绝对不是线程安全的:两个线程可以轻松地踩到对方的数据,而且在计算持续时间时,没有什么能阻止线程使用“陈旧”的数据。
请使用Stopwatch
类 – 这就是它的目的。 无可否认,如果您想要使用多个线程中的一个实例,则需要采取正常的步骤来确保安全,但总的来说,您将处于更好的位置。 不可否认, Stopwatch
还远远不够完美 – 请参阅下面的问题和评论以获取更多详细信息 – 但至less应该为此typesdevise。 (谁知道,这可能是固定的一段时间…)
这里有一个很好的讨论,更多地关注为什么你的例子不是线程安全的机制和原因。
总而言之,首先,你的静态variables将被共享。 如果你可以使它们成为局部variables,即使它们是静态方法的本地variables,它们仍然会得到自己的栈帧,因此是线程安全的。 另外,如果你另外保护你的静态variables(例如,在这个线程中其他人提到的锁和/或其他multithreading编程技术),你也可以让你的示例静态类是线程安全的。
其次,因为你的例子没有引入你修改的外部variables实例或者其他状态可能会被另一个线程执行的外部variables实例,所以你的例子在这方面也是线程安全的。
你的计时器类绝对不是线程安全的。 您应该创build一个普通的类并在每次需要测量时间时实例化它:
Timer timer = new Timer(); timer.Start(); //... timer.Stop(); decimal duration = timer.Duration();
更好的是,有一个内置的.NET类完全做到这一点:
Stopwatch sw = Stopwatch.StartNew(); sw.Stop(); TimeSpan duration = sw.Elapsed;
是的,你是对的,这个类的静态成员/访问者将导致它们被不同的用户覆盖。
这就是为什么你有实例和非静态成员。