Windows 线程(十四) 用户态多线程同步方式总结
用户态下线程同步效率测试
话不多说, 直接上代码
#include <Windows.h>
#include <process.h>
#include <tchar.h>
CONST INT g_LoopCount = 1000000;
volatile INT g_Value = 0;
typedef VOID(CALLBACK *THREADFUNC)();
UINT WINAPI ThreadRunFunc(LPVOID lParam)
{
THREADFUNC op = (THREADFUNC)lParam;
for (INT i = 0; i < g_LoopCount; ++i)
{
// 同步的方式读取或写入数据
op();
}
return 0;
}
VOID CompareStart(LPTSTR pszText, UINT uThreadsNum, THREADFUNC pFunc)
{
HANDLE* pThreads = new HANDLE[uThreadsNum];
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
for (UINT i = 0; i < uThreadsNum; ++i)
{
pThreads[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadRunFunc, pFunc, 0, NULL);
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
// 获取当前线程实际运行的时间 是线程执行代码所用的时间
//GetThreadTimes
// 根据CPU频率来计算最精准的时间
LARGE_INTEGER largeFreq, largeBegin, largeEnd;
// 获取CPU频率 通过硬件获取的 很精准
QueryPerformanceFrequency(&largeFreq);
// 获取时间周期
QueryPerformanceCounter(&largeBegin);
WaitForMultipleObjects(uThreadsNum, pThreads, TRUE, INFINITE);
QueryPerformanceCounter(&largeEnd);
ULONGLONG ullTime = (largeEnd.QuadPart - largeBegin.QuadPart) * 1000 / largeFreq.QuadPart; // 1/1000秒
_tprintf(TEXT("测试 [%s] 用时 [%llu], 线程数: [%d]\n"), pszText, ullTime, uThreadsNum);
for (UINT i = 0; i < uThreadsNum; ++i)
{
CloseHandle(pThreads[i]);
}
delete[] pThreads;
}
// 直接读取
VOID WINAPI DirectRead()
{
INT value = g_Value;
}
// 直接写
VOID WINAPI DirectWrite()
{
g_Value = 0;
}
// 原子操作写
VOID WINAPI AtomWrite()
{
InterlockedExchangeAdd((LONG*)&g_Value, 1);
}
// 旋转锁读
volatile BOOL g_bRuning = FALSE;
VOID WINAPI SpinLockRead()
{
while (InterlockedExchange((LONG*)&g_bRuning, TRUE) == TRUE)
Sleep(0);
INT nValue = g_Value;
InterlockedExchange((LONG*)&g_bRuning, FALSE);
}
// 旋转锁写
VOID WINAPI SpinLockWrite()
{
while (InterlockedExchange((LONG*)&g_bRuning, TRUE) == TRUE)
Sleep(0);
g_Value = 0;
InterlockedExchange((LONG*)&g_bRuning, FALSE);
}
// 临界区读
CRITICAL_SECTION g_Cs;
VOID WINAPI CriticalSectionRead()
{
EnterCriticalSection(&g_Cs);
INT nValue = g_Value;
LeaveCriticalSection(&g_Cs);
}
// 临界区写
VOID WINAPI CriticalSectionWrite()
{
EnterCriticalSection(&g_Cs);
g_Value = 0;
LeaveCriticalSection(&g_Cs);
}
// Slim锁读
SRWLOCK g_Srw;
VOID WINAPI SlimRead()
{
AcquireSRWLockShared(&g_Srw);
INT nValue = g_Value;
ReleaseSRWLockShared(&g_Srw);
}
// Slim锁写
VOID WINAPI SlimWrite()
{
AcquireSRWLockExclusive(&g_Srw);
INT nValue = g_Value;
ReleaseSRWLockExclusive(&g_Srw);
}
INT main()
{
_tsetlocale(0, TEXT(""));
// 测试 1--16 个线程
for (INT i = 1; i <= 16; ++i)
{
CompareStart(TEXT("直接读取"), i, DirectRead);
CompareStart(TEXT("直接写"), i, DirectWrite);
// 用户态下的同步方式
CompareStart(TEXT("原子操作写"), i, AtomWrite);
CompareStart(TEXT("旋转锁读"), i, SpinLockRead);
CompareStart(TEXT("旋转锁写"), i, SpinLockWrite);
InitializeCriticalSection(&g_Cs);
CompareStart(TEXT("临界区读"), i, CriticalSectionRead);
CompareStart(TEXT("临界区写"), i, CriticalSectionWrite);
DeleteCriticalSection(&g_Cs);
InitializeSRWLock(&g_Srw);
CompareStart(TEXT("Slim锁读"), i, SlimRead);
CompareStart(TEXT("Slim锁写"), i, SlimWrite);
_tprintf(TEXT("========================================\n"));
}
return 0;
}运行结果是每个电脑都不一样的
请大家自行编译测试.
使用内核对象来同步
它可以跨进程同步数据
详情下节课了解.
未完待续...
如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-06-29 at 07:31 am