天天看點

同步機制的性能比較

本篇文章參考 windows核心程式設計  P215

下圖這個簡單的測試會産生1個,2個,4個線程,這些線程會使用不同的線程同步機制來重複執行相同的任務,在雙核處理器上執行結果如下:

線程/微秒  volatile讀取  volatile寫入  interlocked遞增  關鍵段  SRWLock共享模式  SRWLock獨占模式   互斥量

    1                 8                   8                      35                          66                  66                           67                       1060

    2                 8                   76                    153                     268                134                         148                      11082

    4                 9                  145                   361                     768                244                         307                      23785

1. 讀取一個volatile長整形值

LONG lValue = value;

volatile 讀取非常快,因為它不需要進行任何同步,直接從記憶體中取出資料,與CPU高速緩存完全無關

2. 寫入一個volatile值

單線程的時候隻有8微秒,兩個線程的時候,我們很顯然認為執行相同的操作,時間隻不過是加倍,但是實際在雙處理器的機器上時間消耗的更多,為76。這是因為CPU之間必須互相通信,保證緩存的一緻性,四個線程時,時間加了一倍,因為在雙線程時,消耗的時間已經考慮到了cpu之間的互相通信,這裡僅僅是工作量加倍。

如果cpu數量增加,消耗的時間還會增加,因為互相通信花費的時間更長。

3. 使用interlockedIncrement 來安全地遞增一個volatile值

InterlockedIncrement(&value);

interlockedIncrement 要比volatile讀寫都要慢,因為它要保證在同一時刻cpu之間隻有一個cpu能夠通路并修改它。使用兩個線程比使用一個線程慢的多,因為cpu之間需要通信,來保證告訴緩存的一緻性。4個線程更慢,因為工作量加倍。 如果在4個cpu的機器上 性能可能更糟,因為要在4個cpu之間進行通信。

4. 使用關鍵段來讀取volatile長整形值

關鍵段比較慢,因為存在進入和離開兩個過程。 此外,進入和離開關鍵段需要修改CRITICAL_SECTION結構中的多個字段,是以當發生争奪現象的時候,關鍵段執行要慢得多。4個線程時,花費的時間超過了2個線程的兩倍還多,因為上下文的切換增大了資源争奪的可能性。

5.  SRWLock 來讀取volatile長整型值

當隻有一個線程的時候,SRWLock 執行讀取和寫入操作的時間幾乎相同。

當有兩個線程的時候,SRWLock 執行讀操作性能要優于寫操作,因為讀操作可以同時讀取,而寫操作是互斥的。 與四個線程較為相似。

此外,由于多個線程會不斷地寫入鎖的字段以及它保護的資料,是以各cpu必須在他們的高速緩存之間來回傳輸資料。

6.  使用核心對象  互斥量

性能最差,這是因為等待互斥量以及後來釋放互斥量需要線程每次都在使用者态和核心态之間來回進行切換,而這種切換的時間消耗是非常巨大的,在兩個線程或者四個線程執行時,性能會急劇下降。

如果我們希望在應用系統中得到最佳性能,首先應該嘗試不要使用共享資料,然後依次使用volatile讀取,volatile寫入,Interlocked API, SRWLock 以及 關鍵段。 如果都不能滿足要求的話,在去嘗試使用核心對象。

繼續閱讀