簡要將Win32編程中四種同步方式的性能作比較,分別有CriticalSection,Semaphore,Mutex,Event。
已經簡要封裝成了auto_locker,代碼如下:
Lock.h
#pragma once
#include <windows.h>
class ILock
{
public:
virtual void lock() = 0;
virtual void unlock() = 0;
};
//臨界區封裝
class _CCriticalSection : public ILock
{
public:
_CCriticalSection(DWORD dwSpinCount = 0);
~_CCriticalSection();
DWORD setCSspincount(DWORD dwSpinCount = 0);
virtual void lock();
virtual void unlock();
private:
CRITICAL_SECTION m_cs;
_CCriticalSection(const _CCriticalSection&);
_CCriticalSection& operator=(const _CCriticalSection&);
};
//信號量封裝
class _CSemaphore : public ILock
{
public:
_CSemaphore(__in LONG lInitialCount, __in LONG lMaximumCount);
~_CSemaphore();
virtual void lock();
virtual void unlock();
private:
HANDLE m_hSemaphore;
_CSemaphore(const _CSemaphore&);
_CSemaphore& operator=(const _CSemaphore&);
};
//互斥器封裝
class _CMutex : public ILock
{
public:
_CMutex();
~_CMutex();
virtual void lock();
virtual void unlock();
private:
HANDLE m_hMutex;
_CMutex(const _CMutex&);
_CMutex& operator=(const _CMutex&);
};
//事件封裝
class _CEvent : public ILock
{
public:
_CEvent();
~_CEvent();
virtual void lock();
virtual void unlock();
private:
HANDLE m_hEvent;
_CEvent(const _CEvent&);
_CEvent& operator=(const _CEvent&);
};
class CAuto_locker
{
public:
CAuto_locker(ILock&);
~CAuto_locker();
private:
ILock& m_lock;
};
Lock.cpp
#include "stdafx.h"
#include "Lock.h"
#include <assert.h>
_CCriticalSection::_CCriticalSection(DWORD dwSpinCount /* = 0 */)
{
if (dwSpinCount > 0)
{
::InitializeCriticalSectionAndSpinCount(&m_cs, dwSpinCount);
}
else
{
::InitializeCriticalSection(&m_cs);
}
}
_CCriticalSection::~_CCriticalSection()
{
::DeleteCriticalSection(&m_cs);
}
void _CCriticalSection::lock()
{
::EnterCriticalSection(&m_cs);
}
void _CCriticalSection::unlock()
{
::LeaveCriticalSection(&m_cs);
}
DWORD _CCriticalSection::setCSspincount(DWORD dwSpinCount /* = 0 */)
{
return ::SetCriticalSectionSpinCount(&m_cs, dwSpinCount);
}
_CSemaphore::_CSemaphore(__in LONG lInitialCount, __in LONG lMaximumCount)
{
assert(lInitialCount >= 0 && lMaximumCount >= 0 && lInitialCount <= lMaximumCount);
m_hSemaphore = ::CreateSemaphore(NULL, lInitialCount, lMaximumCount, NULL);
//失敗返回NULL
assert(m_hSemaphore);
}
_CSemaphore::~_CSemaphore()
{
CloseHandle(m_hSemaphore);
}
void _CSemaphore::lock()
{
WaitForSingleObject(m_hSemaphore, INFINITE);
}
void _CSemaphore::unlock()
{
::ReleaseSemaphore(m_hSemaphore, 1, NULL);
}
_CMutex::_CMutex()
{
m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
assert(m_hMutex);
}
_CMutex::~_CMutex()
{
::CloseHandle(m_hMutex);
}
void _CMutex::lock()
{
WaitForSingleObject(m_hMutex, INFINITE);
}
void _CMutex::unlock()
{
::ReleaseMutex(m_hMutex);
}
_CEvent::_CEvent()
{
m_hEvent = ::CreateEvent(NULL, FALSE, TRUE, NULL);
assert(m_hEvent);
}
_CEvent::~_CEvent()
{
::CloseHandle(m_hEvent);
}
void _CEvent::lock()
{
WaitForSingleObject(m_hEvent, INFINITE);
}
void _CEvent::unlock()
{
SetEvent(m_hEvent);
}
CAuto_locker::CAuto_locker(ILock& locker) : m_lock(locker)
{
m_lock.lock();
}
CAuto_locker::~CAuto_locker()
{
m_lock.unlock();
}
test.cpp
#include "stdafx.h"
#include <iostream>
#include <process.h>
#include <time.h>
#include <typeinfo.h>
#include "Lock.h"
_CCriticalSection g_cs;
_CSemaphore g_Semaphore(1,1);
_CMutex g_mutex;
_CEvent g_event;
void LockerTest(ILock& auto_locker)
{
clock_t tStart, tEnd;
int i = 0;
tStart = clock();
while (i < 100000)
{
CAuto_locker lock(auto_locker);
i++;
}
tEnd = clock();
std::cout << typeid(auto_locker).name() << " 總共用時: " << (tEnd - tStart) << " ms." << std::endl;
}
unsigned int WINAPI TestThread(void *pParam)
{
int index = (int)pParam;
switch (index)
{
case 0:
LockerTest(g_cs);
break;
case 1:
LockerTest(g_mutex);
break;
case 2:
LockerTest(g_Semaphore);
break;
case 3:
LockerTest(g_event);
break;
default:
break;
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread[4];
for (int i = 0; i < 4; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, &TestThread, (void *)i, 0, 0);
WaitForSingleObject(hThread[i], INFINITE);
}
WaitForMultipleObjects(4, hThread, TRUE, INFINITE);
for (int i = 0; i < 4; i++)
{
::CloseHandle(hThread[i]);
}
system("pause");
return 0;
}
對於test.cpp,對於每一個auto_locker進行了單獨一個線程的測試,測試100000次鎖的總耗時,來判斷其性能。
經過多次測試,平均結果CriticalSection的性能是其它三種的5倍左右,可見在單進程中,線程互斥CriticalSection有絕對的優勢。