秒表经过时间线程安全

Nom*_*101 4 .net c# multithreading thread-safety

好吧,我有一个相当简单的问题,但我找不到简洁的答案。我想知道在读取仍在运行的lock()一段时间的已用属性时是否需要担心调用语句。Stopwatch

这也是Stopwatch我应该用来测量线程运行时间的东西。我读过其他类似的问题,DispatchTimer可以使用 a 。我也研究过使用事件,但是对于如此简单的事情来说,这似乎是很大的开销,如果这是完全错误的并且我应该使用事件,请告诉我。一些简单的代码来说明我在说什么。

 class foo
 {
      private bool _isRunning { get; set; }
      private Stopwatch sw { get; set; }
      public void StartThread()
      {
          this._isRunning = true;
          new Thread(new ThreadStart(this.DoWork)).Start();
          this.sw.Restart();
      }     
      public void StopThread()
      {
          this._isRunning = false;
          this.sw.Stop();
      }
      private void DoWork()
      {
          while(this._isRunning)
          {
               //Do Stuff
          }
      }
      public TimeSpan GetRuntime()
      {
          return this.sw.Elapsed;
      }
      public foo()
      {
          _isRunning = false;
          sw = new Stopwatch();
      }
 }
Run Code Online (Sandbox Code Playgroud)

假设在使用上述类的应用程序中,我要在GetRuntime()停止之前从不同的线程调用,Stopwatch我需要添加一条lock()语句以确保获得正确的数据,并且不会阻止Stopwatch继续运行。或者我认为它不需要并且lock()照原样就可以了,这是正确的吗?

我确实明白,理论上您可以根据需要运行任意数量的读取,我只是很好奇,因为如果发生变化,已用属性后备存储会不断被写入。我已经阅读了很多有关线程安全的信息,但我只是在寻找澄清和确认,我确实正确地思考了这一点。

Dan*_*ant 5

MSDN文档指出,关于 Stopwatch,“不保证任何实例成员都是线程安全的”。请注意,这里肯定存在理论上的漏洞,因为它在内部使用“长”滴答计数,并且在 32 位处理器上更新 long 不是原子操作。您可能会看到部分更新(因此损坏)的值。您可能不会注意到,直到 Ticks 恰好超出 32 位边界,此时您可能会遇到非常意外的罕见错误(您可能会读取 Int32.MaxValue,后跟 0,然后是 Int32.MaxValue + 1,如果您在错误的时刻查询,则会在经过时间上产生非常大的差异。)

  • @Nomad101:文档说**不保证线程安全**。问“好吧,如果我只坚持功能集的这一部分,是否安全?” 然后将影响安全和正确性的决策基于可能发生变化的实施细节。你对线程安全的态度不应该是“我能逃脱的最危险的操作是什么?” 而是“我如何*保证*我安全地访问这个数据结构?” (3认同)
  • @Nomad101:你问“如果我坚持使用 32 位返回值,我会好吗?” 文档没有说“如果您坚持使用 32 位返回值,那么该操作是线程安全的。” 它说的是相反的:**不保证是线程安全的**。问“好吧,如果我坚持这种特殊的使用模式,它是线程安全的吗?” 表示您正在考虑尝试做一些危险的事情。 (2认同)