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); 是成对使用的

浙公网安备 33010602011771号