第一个文本框是奖池,右面三个文本框是三个线程抢到的红包数,程序运行结果如下:
解决资源抢占问题,WIN32提供两种方式:临界区和互斥体。
临界区和互斥体的对比:
1、临界区只能应用於单个进程间的线程控制,互斥体可以跨进程;
2、互斥体可以设定阻塞等待超时,临界区不能;
3、线程意外终结时,互斥体可以避免死锁;
4、互斥体效率比临界区低。
临界区实现
// RedPack.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
/************************************************************************/
/*
抢红包多线程练习
*/
/************************************************************************/
#include <WINDOWS.H>
#include <STDIO.H>
#include <TCHAR.H>
#include "resource.h"
HWND hEditTotal, hEditA, hEditB, hEditC;
CRITICAL_SECTION csTotal;
DWORD WINAPI ThreadA(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
EnterCriticalSection(&csTotal);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditA, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditA, szBuffer);
LeaveCriticalSection(&csTotal);
// 延迟
Sleep(50);
}
return 0;
}
DWORD WINAPI ThreadB(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
EnterCriticalSection(&csTotal);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditB, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditB, szBuffer);
LeaveCriticalSection(&csTotal);
// 延迟
Sleep(50);
}
return 0;
}
DWORD WINAPI ThreadC(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
EnterCriticalSection(&csTotal);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditC, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditC, szBuffer);
LeaveCriticalSection(&csTotal);
// 延迟
Sleep(50);
}
return 0;
}
// 启动抽奖线程,设置该线程的目的是阻塞等待其他线程结束,然后清理句柄
DWORD WINAPI ThreadStart(LPVOID p)
{
HANDLE handles[3];
SetWindowText(hEditA, TEXT("0"));
SetWindowText(hEditB, TEXT("0"));
SetWindowText(hEditC, TEXT("0"));
handles[0] = CreateThread(0,0,ThreadA,0,0,0);
handles[1] = CreateThread(0,0,ThreadB,0,0,0);
handles[2] = CreateThread(0,0,ThreadC,0,0,0);
WaitForMultipleObjects(3, handles, TRUE, INFINITE);
CloseHandle(handles[0]);
CloseHandle(handles[1]);
CloseHandle(handles[2]);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
hEditTotal = GetDlgItem(hDlg, IDC_EDIT_TOTAL);
hEditA = GetDlgItem(hDlg, IDC_EDIT_A);
hEditB = GetDlgItem(hDlg, IDC_EDIT_B);
hEditC = GetDlgItem(hDlg, IDC_EDIT_C);
SetWindowText(hEditTotal, TEXT("0"));
SetWindowText(hEditA, TEXT("0"));
SetWindowText(hEditB, TEXT("0"));
SetWindowText(hEditC, TEXT("0"));
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
CreateThread(0,0,ThreadStart,0,0,0);
return TRUE;
}
}
return TRUE;
}
case WM_CLOSE:
{
EndDialog(hDlg, 0);
return TRUE;
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
InitializeCriticalSection(&csTotal);
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDlgProc);
return 0;
}
互斥体实现
// RedPack.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
/************************************************************************/
/*
抢红包多线程练习
*/
/************************************************************************/
#include <WINDOWS.H>
#include <STDIO.H>
#include <TCHAR.H>
#include "resource.h"
HWND hEditTotal, hEditA, hEditB, hEditC;
HANDLE hMutex;
DWORD WINAPI ThreadA(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
WaitForSingleObject(hMutex, INFINITE);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditA, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditA, szBuffer);
ReleaseMutex(hMutex);
// 延迟
Sleep(50);
}
return 0;
}
DWORD WINAPI ThreadB(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
WaitForSingleObject(hMutex, INFINITE);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditB, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditB, szBuffer);
ReleaseMutex(hMutex);
// 延迟
Sleep(50);
}
return 0;
}
DWORD WINAPI ThreadC(LPVOID p)
{
int nTotal;
int nValue;
TCHAR szBuffer[100];
BOOL bFlag = TRUE;
while (bFlag)
{
WaitForSingleObject(hMutex, INFINITE);
GetWindowText(hEditTotal, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nTotal);
GetWindowText(hEditC, szBuffer, 100);
_stscanf(szBuffer, TEXT("%d"), &nValue);
if (nTotal >= 50)
{
nTotal -= 50;
nValue += 50;
}
else
{
bFlag = FALSE;
}
_stprintf(szBuffer, TEXT("%d"), nTotal);
SetWindowText(hEditTotal, szBuffer);
_stprintf(szBuffer, TEXT("%d"), nValue);
SetWindowText(hEditC, szBuffer);
ReleaseMutex(hMutex);
// 延迟
Sleep(50);
}
return 0;
}
// 启动抽奖线程,设置该线程的目的是阻塞等待其他线程结束,然后清理句柄
DWORD WINAPI ThreadStart(LPVOID p)
{
HANDLE handles[3];
hMutex = CreateMutex(0, FALSE, "MyTag");
SetWindowText(hEditA, TEXT("0"));
SetWindowText(hEditB, TEXT("0"));
SetWindowText(hEditC, TEXT("0"));
handles[0] = CreateThread(0,0,ThreadA,0,0,0);
handles[1] = CreateThread(0,0,ThreadB,0,0,0);
handles[2] = CreateThread(0,0,ThreadC,0,0,0);
WaitForMultipleObjects(3, handles, TRUE, INFINITE);
CloseHandle(handles[0]);
CloseHandle(handles[1]);
CloseHandle(handles[2]);
CloseHandle(hMutex);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
hEditTotal = GetDlgItem(hDlg, IDC_EDIT_TOTAL);
hEditA = GetDlgItem(hDlg, IDC_EDIT_A);
hEditB = GetDlgItem(hDlg, IDC_EDIT_B);
hEditC = GetDlgItem(hDlg, IDC_EDIT_C);
SetWindowText(hEditTotal, TEXT("0"));
SetWindowText(hEditA, TEXT("0"));
SetWindowText(hEditB, TEXT("0"));
SetWindowText(hEditC, TEXT("0"));
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
CreateThread(0,0,ThreadStart,0,0,0);
return TRUE;
}
}
return TRUE;
}
case WM_CLOSE:
{
EndDialog(hDlg, 0);
return TRUE;
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDlgProc);
return 0;
}