第一個文本框是獎池,右面三個文本框是三個線程搶到的紅包數,程序運行結果如下:
解決資源搶佔問題,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;
}