我有一个静态的定时器类会被任何网页被调用,以计算每一页都有了多长时间来构建。
我的问题是在静态类线程安全的? 在我的例子会并发用户造成一个问题,我的开始和结束时间? 例如,不同的线程覆盖我的启动和停止值。
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母版。)
静态方法是没有本质上就是线程安全的。 他们由CLR比实例方法处理没有区别。 不同的是,一个一般应尽量使他们线程安全的。 (我想不出任何.NET BCL静态方法这不是线程安全的。)实例方法,因为典型的模式是创建一个对象,并从一个线程重复使用它往往不是线程安全的,如果它也必须从多个线程使用,统筹涉及包括确保该对象的安全使用。 在很多情况下,这更合适的统筹代码做多的对象本身。 (通常你要进行的操作有效的原子的整个序列 - 一些东西,不能在目标之内完成)
您的Timer
类是最绝对不是线程安全的:两个线程可以在对方的轻松数据跺脚,并没有什么,从计算时间时使用“陈旧”数据停止一个线程。
使用Stopwatch
类,而不是-这就是它的存在了。 诚然,如果你想使用多线程一个实例,你需要采取正常的步骤,以确保安全,但你会在一般一个更好的位置。 诚然Stopwatch
远非完美太-看到这个问题和下面的评论更多的细节-但它至少是个什么类型的设计。 (谁知道,它可以是固定的一段时间......)
这是一个很好的讨论在这里是更侧重于机制和原因,为什么你的例子是不是线程安全的。
总之,第一,你的静态变量将被共享。 如果你可以让他们的局部变量,即使他们是本地的一个静态方法,他们仍然会得到自己的堆栈帧,因此是线程安全的。 另外,如果你,否则保护您的静态变量(即锁和/或由其他人在这个线程中提到的其他多线程编程技术),你也可以让你的样品静态类线程安全的。
其次,因为你的例子并不在其中修改或其状态可能会被另一个线程采取行动外部变量情况下采取,你的例子是线程安全在这方面也是如此。
您的计时器类绝对不是线程安全的。 您应该创建一个普通的类和每一个你需要测量的时间的时间实例吧:
Timer timer = new Timer();
timer.Start();
//...
timer.Stop();
decimal duration = timer.Duration();
更妙的是,有一个内置的正是这么做的.NET类:
Stopwatch sw = Stopwatch.StartNew();
sw.Stop();
TimeSpan duration = sw.Elapsed;
是的,你说得对,这个类的静态成员/存取将导致他们由不同的用户覆盖。
这就是为什么你必须实例和非静态成员。