2013-12-13 39 views
1

WinAPI下有WaitForSingleObject()和ReleaseMutex()函數對。還有Interlocked *()函數系列。我決定在捕獲單個互斥鎖和交換互鎖變量之間檢查性能。WaitForSingleObject vs Interlocked *

HANDLE mutex; 
WaitForSingleObject(mutex, INFINITE); 
// .. 
ReleaseMutex(mutex); 

// 0 unlocked, 1 locked 
LONG lock = 0; 
while(InterlockedCompareExchange(&lock, 1, 0)) 
    SwitchToThread(); 
// .. 
InterlockedExchange(&lock, 0); 
SwitchToThread(); 

我測量了這兩種方法之間的性能,發現使用Interlocked *()的速度快了大約38%。爲什麼這樣?

這裏是我的性能測試:

#include <windows.h> 
#include <iostream> 
#include <conio.h> 
using namespace std; 

LONG interlocked_variable = 0; // 0 unlocked, 1 locked 
int run      = 1; 

DWORD WINAPI thread(LPVOID lpParam) 
{ 
    while(run) 
    { 
     while(InterlockedCompareExchange(&interlocked_variable, 1, 0)) 
      SwitchToThread(); 
     ++(*((unsigned int*)lpParam)); 
     InterlockedExchange(&interlocked_variable, 0); 
     SwitchToThread(); 
    } 

    return 0; 
} 

int main() 
{ 
    unsigned int num_threads; 
    cout << "number of threads: "; 
    cin >> num_threads; 
    unsigned int* num_cycles = new unsigned int[num_threads]; 
    DWORD s_time, e_time; 

    s_time = GetTickCount(); 
    for(unsigned int i = 0; i < num_threads; ++i) 
    { 
     num_cycles[i] = 0; 
     HANDLE handle = CreateThread(NULL, NULL, thread, &num_cycles[i], NULL, NULL); 
     CloseHandle(handle); 
    } 
    _getch(); 
    run = 0; 
    e_time = GetTickCount(); 

    unsigned long long total = 0; 
    for(unsigned int i = 0; i < num_threads; ++i) 
     total += num_cycles[i]; 
    for(unsigned int i = 0; i < num_threads; ++i) 
     cout << "\nthread " << i << ":\t" << num_cycles[i] << " cyc\t" << ((double)num_cycles[i]/(double)total) * 100 << "%"; 
    cout << "\n----------------\n" 
     << "cycles total:\t" << total 
     << "\ntime elapsed:\t" << e_time - s_time << " ms" 
     << "\n----------------" 
     << '\n' << (double)(e_time - s_time)/(double)(total) << " ms\\op\n"; 

    delete[] num_cycles; 
    _getch(); 
    return 0; 
} 
+1

互斥鎖是跨進程同步的內核對象,因此每個鎖定/解鎖都涉及上下文切換。 [見此處](http://msdn.microsoft.com/en-us/magazine/cc163726.aspx)進行相關討論。 –

+1

據我所知,互斥鎖更適合多個進程之間的同步。您可能還想嘗試一個關鍵部分。 – Paul

+0

你是如何測試性能的?在鎖上有沒有實際的爭用? –

回答

3

WaitForSingleObject並不一定會更快。它涵蓋了更廣泛的同步場景範圍,尤其是您可以等待不屬於您的進程並因此進程間同步的句柄。考慮到所有這一切,只有根據您的測試慢了38%。

如果您的流程中包含了所有內容,並且每納秒計數一次,InterlockedXxx可能是更好的選擇,但它絕對不是絕對優越的選擇。

此外,你可能想看看Slim Reader/Writer (SRW) Locks API。您或許可以純粹基於InterlockedXxx構建類似的類/功能,並且性能略好,但重要的是,通過SRW,您可以立即使用它,並具備記錄的行爲,穩定且性能良好。

3

您沒有比較等效的鎖,因此性能如此不同並不奇怪。

互斥鎖允許跨進程鎖定,由於其提供的靈活性,它可能是最昂貴的鎖定方法之一。當你阻塞一個鎖時,它通常會讓你的線程進入睡眠狀態,直到你被喚醒後纔會使用cpu。這允許其他代碼使用cpu。

您的InterlockedCompareExchange()代碼是一個簡單的自旋鎖。你會刻錄CPU等待你的鎖。

您可能還需要尋找到Critical Sections(不是互斥的開銷更少)和Slim Reader/Writer Locks(可用於互斥如果你總是獲取排它鎖並提供分數更快的性能比無爭議的使用關鍵部分,根據我的測試)。

您可能還想讀肯尼克爾的"The Evolution of Synchronization in Windows and C++"和Preshing的鎖相關的東西,herehere

相關問題