33win32编程基础——线程安全之互斥体实现多线程抢红包实验

#include <Windows.h>
#include "resource.h"
#include <stdio.h>
HINSTANCE hins;
HANDLE  Hmutex;
DWORD WINAPI  ThreadH1Proc(  __in  LPVOID hwndDlg){
	int flag = 1;
	TCHAR sz[20];
	int EnvCount;
	int MyEnv=0;
	while(flag)
	{
		WaitForSingleObject(Hmutex,-1);    //相当于进入临界区
		GetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz,20);
		swscanf(sz,TEXT("%d"),&EnvCount);
		if(EnvCount>=50)
		{
			EnvCount -=50;
			MyEnv +=50;
		}else{
			flag = 0;
		}

		swprintf(sz,TEXT("%d"),EnvCount);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz);
		swprintf(sz,TEXT("%d"),MyEnv);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_H1,sz);
		ReleaseMutex(Hmutex);      //相当于离开临界区

		Sleep(100);
	}

	return TRUE;
}

DWORD WINAPI  ThreadH2Proc(  __in  LPVOID hwndDlg){
	int flag = 1;
	TCHAR sz[20];
	int EnvCount;
	int MyEnv=0;
	while(flag)
	{
		WaitForSingleObject(Hmutex,-1);  //当第一个线程wait到的时候,会改变互斥体为未通知状态,然后继续执行,执行完毕,利用ReleaseMutex把互斥体变为已通知状态,让别的线程执行(单核cpu有同步的功能,多核cpu只有互斥)。
		GetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz,20);
		swscanf(sz,TEXT("%d"),&EnvCount);
		if(EnvCount>=50)
		{
			EnvCount -=50;
			MyEnv +=50;
		}else{
			flag = 0;
		}

		swprintf(sz,TEXT("%d"),EnvCount);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz);
		swprintf(sz,TEXT("%d"),MyEnv);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_H2,sz);
		ReleaseMutex(Hmutex);

		Sleep(100);
	}
	return TRUE;
}

DWORD WINAPI  ThreadH3Proc(  __in  LPVOID hwndDlg){
	int flag = 1;
	TCHAR sz[20];
	int EnvCount;
	int MyEnv=0;
	while(flag)
	{
		WaitForSingleObject(Hmutex,-1);
		GetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz,20);
		swscanf(sz,TEXT("%d"),&EnvCount);
		if(EnvCount>=50)
		{
			EnvCount -=50;
			MyEnv +=50;
		}else{
			flag = 0;
		}

		swprintf(sz,TEXT("%d"),EnvCount);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_ALL,sz);
		swprintf(sz,TEXT("%d"),MyEnv);
		SetDlgItemText(HWND(hwndDlg),IDC_EDIT_H3,sz);
		ReleaseMutex(Hmutex);

		Sleep(100);
	}
	return TRUE;
}

DWORD WINAPI  ThreadMainProc(  __in  LPVOID hwndDlg){
	HANDLE hand[3];
 
  
    //然后启动3个线程开始抢,第二个参数为FALSE相当于刚开始没有线程拥有这个互斥体的权限,等待第一个使用它的线程拥有它。
	Hmutex = CreateMutex(NULL,FALSE,TEXT("XYZ"));

    hand[0] = CreateThread(NULL,NULL,ThreadH1Proc,hwndDlg,0,NULL);
    hand[1] = CreateThread(NULL,NULL,ThreadH2Proc,hwndDlg,0,NULL);
    hand[2] = CreateThread(NULL,NULL,ThreadH3Proc,hwndDlg,0,NULL);
 
    WaitForMultipleObjects(3,hand,TRUE,-1);

    CloseHandle(hand[0]);
    CloseHandle(hand[1]);
    CloseHandle(hand[2]);
	CloseHandle(Hmutex);
	

	return TRUE;
};

BOOL CALLBACK DialogProc(  HWND hwndDlg,   UINT uMsg,   WPARAM wParam, 
  LPARAM lParam){

	   switch(uMsg)
    {
        case WM_COMMAND:
        {
            WORD Id=LOWORD(wParam);
            WORD EventId = HIWORD(wParam);
            switch(Id)
            {
                case IDC_BUTTON_BEGIN:
                    {
                        HANDLE  HMain = ::CreateThread(NULL,NULL,ThreadMainProc,(LPVOID)hwndDlg,0,NULL);
                    }
                default:
                    {
                        return FALSE;
                    }
 
            }
            return 0;
        }
        case WM_CLOSE:
            {
                EndDialog(hwndDlg,0);
                return 0;
            }
        case WM_INITDIALOG:
            {
                SetDlgItemText(hwndDlg,IDC_EDIT_ALL,TEXT("0"));
                SetDlgItemText(hwndDlg,IDC_EDIT_H1,TEXT("0"));
                SetDlgItemText(hwndDlg,IDC_EDIT_H2,TEXT("0"));
                SetDlgItemText(hwndDlg,IDC_EDIT_H3,TEXT("0"));
                return 0;
            }
    }
	  return FALSE;
};

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR  lpCmdLine,int  nCmdShow)
{
    //如果有界面的程序,主线程就是界面的,不要做什么逻辑操作,
    //重启新的线程做逻辑操作,不然界面容易卡死。
    hins = hInstance;
     
 
    DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,DialogProc);
 
    return 0;
}

上边是以互斥体实现的抢红包实验。  

输入红包金额,3个线程同时抢红包,每次抢50,最后抢到的金额总和等于最开始输入的。

  如果小于50就停止抢红包。

注意:

Hmutex = CreateMutex(NULL,FALSE,TEXT("XYZ"));
和CloseHandle(Hmutex)是成对使用的。

  CloseHandle只是关闭内核对象,计数器减去1,并不一定销毁,只有当记录这个内核对象使用的计算器变为0的时候,才销毁。

WaitForSingleObject(Hmutex,-1);
和
ReleaseMutex(Hmutex);
是成对使用的

  

posted @ 2023-11-03 16:06  一日学一日功  阅读(109)  评论(0)    收藏  举报