淺談線程同步方法性能比較

簡要將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有絕對的優勢。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章