PoEdu培训 Windows班 第三十三课 Windows 线程(十四) 用户态多线程同步方式总结
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第三十三课 Windows 线程(十四) 用户态多线程同步方式总结

文章类别: 培训笔记 0 评论

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;
}

运行结果是每个电脑都不一样的
请大家自行编译测试.

使用内核对象来同步

它可以跨进程同步数据
详情下节课了解.

未完待续...

如有错误,请提出指正!谢谢.

回复