2011-07-12 42 views
4

如果我有一個共享的System.Diagnostics.Stopwatch實例,多個線程可以安全地調用shared.ElapsedTicks並獲得準確的結果嗎?Stopwatch.ElapsedTicks線程安全嗎?

以這種方式使用Stopwatch的共享實例和使用靜態GetTimeStamp()方法之間的線程安全性/準確性方面是否存在差異?

我在測量大約180ms的間隔時間,並發現使用共享實例給了我更大的結果分佈,包括比我預期的更短的顯着數字。

機器有多個CPU(2 *英特爾X5550爲它的價值)

+0

只是爲了澄清 - 我不是問我是否應該在多個線程共享秒錶實例成員 - 這是從鏈接馬格努斯明確提供。我試圖理解/解釋現有代碼的意外行爲,並想知道共享的Stopwatch實例是否會成爲問題。 – Rob

回答

9

MSDN:「任何實例成員不能保證是線程安全的。」

+1

有什麼不對的呢? – Magnus

+0

+1,你的回答是正確的..加上它'Stopwatch.GetTimestamp();'是線程安全的,因爲它是靜態的。 –

4

看着源代碼,它不是線程安全的。

+0

你能推斷出可能發生的不準確情況嗎?我問,因爲雖然我看到了意想不到的結果,但它們不是「不可能」的結果 - 我沒有得到任何負面的測量結果,或者是數量級的結果。即使經過數百萬次的測量。 – Rob

+1

在32位機器上,如果在調用'Start()'或Stop()時調用,則容易撕裂。 (它可能讀取正在寫入的'長時間'字段)。在x64上,它看起來很安全。 – SLaks

+0

是的 - 這就是我猜到的。我在64位上運行雖然.. – Rob

3

您可以使用https://msdn.microsoft.com/en-us/library/dd642243(v=vs.110).aspx

ThreadLocal<T> 

這樣的:

ThreadLocal<Random> _localRandom = new ThreadLocal<Random>(() => new Random()); 
    ThreadLocal<Stopwatch> _localStopwatch = new ThreadLocal<Stopwatch>(() => new Stopwatch()); 

    public void SomeTest() 
    { 
     Action someAction =() => 
      { 
       _localStopwatch.Value.Reset(); 
       _localStopwatch.Value.Start(); 
       Thread.Sleep(_localRandom.Value.Next(100, 500)); 
       _localStopwatch.Value.Stop(); 
       Debug.Print(_localStopwatch.Value.Elapsed.TotalMilliseconds.ToString(CultureInfo.InvariantCulture)); 
      }; 

     var actions = Enumerable.Range(0, 1000).Select(i => someAction).ToArray(); 
     Parallel.Invoke(new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount}, actions); 
    }