zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C/C++ Windows API——多线程加锁与临界区域

C++Windows多线程API 区域 加锁 临界
2023-09-11 14:22:54 时间
// MutexDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>//createMutex
#include <process.h>

//预先声明类
class NormalArgs;
//定义类的成员变量要加名空间(且只能在全局范围定义,不能在类中定义)
typedef void (NormalArgs::*operatorFunc)();

class NormalArgs {
private:
    WORD wCount = 65535;
    DWORD dwCount = 65535;
    double doubleCount = 0;
public:
    void getCountStr(char *str, size_t size);
    void addCount();
    void decCount();
};

class MutexArgs : public NormalArgs {

private:
    HANDLE mutexHandle = NULL;
public:
    MutexArgs();
    ~MutexArgs();
protected:
    void operatorCount(operatorFunc func);
public:
    void addCount();
    void decCount();
};

class CriticalSectionArgs : public NormalArgs {

private:
    CRITICAL_SECTION cs;
public:
    CriticalSectionArgs();
    ~CriticalSectionArgs();
protected:
    void operatorCount(operatorFunc func);
public:
    void addCount();
    void decCount();
};

//类的实现
void NormalArgs::getCountStr(char *str, size_t size) {
    sprintf_s(str, size, "wCount=%d, dwCount=%ld, doubleCount=%lf\n", wCount, dwCount, doubleCount);
}
void NormalArgs::addCount() {
    wCount++;
    dwCount += 100;
    doubleCount += 0.1;
}
void NormalArgs::decCount() {
    wCount--;
    dwCount -= 100;
    doubleCount -= 0.1;
}

MutexArgs::MutexArgs() {
    /*
    CreateMutex作用是找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体
    WINBASEAPI _Ret_maybenull_ HANDLE WINAPI CreateMutexW(
    _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
    _In_ BOOL bInitialOwner,
    _In_opt_ LPCWSTR lpName
    );
    */
    LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL;
    BOOL bInitialOwner = FALSE;
    LPCWSTR lpName = NULL;
    //创建一个匿名互斥对象 
    mutexHandle = CreateMutex(lpMutexAttributes, bInitialOwner, lpName);
}
MutexArgs::~MutexArgs() {
    if (mutexHandle != NULL) {
        //销毁互斥对象,释放资源  
        CloseHandle(mutexHandle);
    }
}
void MutexArgs::operatorCount(operatorFunc func) {
    if (mutexHandle != NULL) {
        /*
        确保拥有互斥对象的线程对被保护资源的独自访问
        WINBASEAPI DWORD WINAPI WaitForSingleObject(
            _In_ HANDLE hHandle,
            _In_ DWORD dwMilliseconds
        );
        WAIT_ABANDONED  0x00000080L
        WAIT_OBJECT_0   0x00000000L
        WAIT_TIMEOUT    0x00000102L
        WAIT_FAILED     0xFFFFFFFF
        */
        DWORD event = WaitForSingleObject(mutexHandle, INFINITE);
        /*
        由于类的非静态成员函数中有一个隐形的this指针,因此,类的成员函数的指针和一般函数的指针的表现形式不一样。
        类的静态成员函数采用与一般函数指针相同的调用方式,而受this指针的影响,类的非静态成员函数与一般函数指针是不兼容的。而且,不同类的this指针是不一样的,因此,指向不同类的非静态成员函数的指针也是不兼容的。指向类的非静态成员函数的指针,在声明时就需要添加类名。

        所以(*func)()调用的是"一般函数的指针",而不能调用"指向类的成员函数的指针"
        */
        (this->*func)();

        //释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问  
        ReleaseMutex(mutexHandle);
    }
}
void MutexArgs::addCount() {
    operatorCount(&NormalArgs::addCount);
}
void MutexArgs::decCount() {
    operatorCount(&NormalArgs::decCount);
}

CriticalSectionArgs::CriticalSectionArgs() {
    //初始化"临界区对象"
    InitializeCriticalSection(&cs);
}

CriticalSectionArgs::~CriticalSectionArgs() {
    //删除"临界区对象"
    DeleteCriticalSection(&cs);
}

void CriticalSectionArgs::operatorCount(operatorFunc func) {
    //进入"临界区"
    EnterCriticalSection(&cs);
    (this->*func)();
    //离开"临界区"
    LeaveCriticalSection(&cs);
}

void CriticalSectionArgs::addCount() {
    operatorCount(&NormalArgs::addCount);
}

void CriticalSectionArgs::decCount() {
    operatorCount(&NormalArgs::decCount);
}

void NormalThreadFunc(LPVOID lpParameter) {
    NormalArgs *normalArgs = (NormalArgs *)lpParameter;
    normalArgs->addCount();
    Sleep(1);
    normalArgs->decCount();
}

void MutexThreadFunc(LPVOID lpParameter) {
    MutexArgs *mutexArgs = (MutexArgs *)lpParameter;
    mutexArgs->addCount();
    Sleep(1);
    mutexArgs->decCount();
}

void CriticalSectionThreadFunc(LPVOID lpParameter) {
    CriticalSectionArgs *criticalSectionArgs = (CriticalSectionArgs *)lpParameter;
    criticalSectionArgs->addCount();
    Sleep(1);
    criticalSectionArgs->decCount();
}

int main()
{
    NormalArgs *normalArgs = new NormalArgs();
    MutexArgs *mutexArgs = new MutexArgs();
    CriticalSectionArgs *criticalSectionArgs = new CriticalSectionArgs();
    //_beginthreadex();
    /*
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
    WINBASEAPI _Ret_maybenull_ HANDLE WINAPI CreateThread(
        _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
        _In_ SIZE_T dwStackSize,
        _In_ LPTHREAD_START_ROUTINE lpStartAddress,
        _In_opt_ __drv_aliasesMem LPVOID lpParameter,
        _In_ DWORD dwCreationFlags,
        _Out_opt_ LPDWORD lpThreadId
    );
    */
    LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
    SIZE_T dwStackSize = 0;
    DWORD dwCreationFlags = 0;
    LPDWORD lpThreadId = NULL;
    const int THREAD_HANDLE_SIZE = 1000;
    HANDLE threadHandles[THREAD_HANDLE_SIZE];

    const int type = 3;
    LPTHREAD_START_ROUTINE lpStartAddresses[type] = { (LPTHREAD_START_ROUTINE)&NormalThreadFunc, (LPTHREAD_START_ROUTINE)&MutexThreadFunc, (LPTHREAD_START_ROUTINE)&CriticalSectionThreadFunc };
    LPVOID lpParameters[type] = { normalArgs, mutexArgs, criticalSectionArgs };
    for (int i = 0; i < type; i++) {
        for (int j = 0; j < THREAD_HANDLE_SIZE; j++) {
            threadHandles[j] = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddresses[i], lpParameters[i], dwCreationFlags, lpThreadId);
        }
        for (int j = 0; j < THREAD_HANDLE_SIZE; j++) {
            //等待一个线程结束运行
            WaitForSingleObject(threadHandles[j], INFINITE);
            CloseHandle(threadHandles[j]);
        }
    }

    const int BUFF_SIZE = 255;
    char normalCountStr[BUFF_SIZE];
    char mutexCountStr[BUFF_SIZE];
    char criticalSectionCountStr[BUFF_SIZE];

    normalArgs->getCountStr(normalCountStr, BUFF_SIZE);
    mutexArgs->getCountStr(mutexCountStr, BUFF_SIZE);
    criticalSectionArgs->getCountStr(criticalSectionCountStr, BUFF_SIZE);

    printf(normalCountStr);
    printf(mutexCountStr);
    printf(criticalSectionCountStr);

    delete normalArgs;
    delete mutexArgs;
    delete criticalSectionArgs;

    system("pause");
    return 0;
}

这里写图片描述