1.WaitForSingleObject
示例代码:
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for(int i=0;i<5;i++)
{
printf("+++++++++\n");
Sleep(1000);
}
return 0;
}
int main(int argc, char* argv[])
{
//创建一个新的线程
HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
NULL, 0, NULL);
DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE);
MessageBox(0,0,0,0);
return 0;
}
2.WaitForMultipleObjects
详情请参见:WaitForSingleObject等待函数
WaitForSingleObject函数在等待成功呢时通常不会修改状态,但是在遇到自动重置事件作为对象时(CreateEvent函数第二个参数是false时),就会自动将事件的状态修改为未通知状态。
代码演示:
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for(int i=0;i<5;i++)
{
printf("+++++++++\n");
Sleep(1000);
}
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for(int i=0;i<3;i++)
{
printf("---------\n");
Sleep(1000);
}
return 0;
}
int main(int argc, char* argv[])
{
HANDLE hArray[2];
//创建一个新的线程
HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
NULL, 0, NULL);
//创建一个新的线程
HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2,
NULL, 0, NULL);
hArray[0] = hThread1;
hArray[1] = hThread2;
DWORD dwCode = ::WaitForMultipleObjects(2, hArray,FALSE,INFINITE);
MessageBox(0,0,0,0);
return 0;
}
3.跨进程的线程控制——互斥体
CreateMutex函数第二个参数是true时,表示初始化创建互斥体占有者立即占用该内核对象,即其他的WaitFor只能阻塞
OpenMutex函数用于在多进程时能够获取其他进程互斥体,并赋予新的句柄。
进程一:
HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");
进程二:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);
//逻辑代码
ReleaseMutex(g_hMutex);
进程三:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);
//逻辑代码
ReleaseMutex(g_hMutex);
这里互斥体可以实现对于多个进程之间线程的控制,假如在进程1中创建一个互斥体,
在进程2中OpenMutex打开一个命名的互斥体,然后使用WaitForSingleObject函数,可以实现对于线程的自愿等待。效果类似前面学习的临界区
互斥体与临界区的区别:
1.临界区只能用于单个进程中线程的控制
互斥体可以用于不同进程中的线程控制,通过WaitForSingleObject函数实现线程的控制
2.互斥体可以设置等待超时,临界区不可以
互斥体可以通过WaitForSingleObject函数第三个参数,实现是否超时
3.线程意外终结时,Mutex可以避免无限等待
如果使用临界区时,中途发生了线程终止,那么就无法“归还令牌”,那么后面的线程就无法获取令牌,线程就无法运行
通过实验可知:互斥体的方式是通过判断线程内核对象是否通知的状态来判断是否等待
如果前面的线程意外终止,那么就会被认定为被通知状态,WaitForSingleObject函数就会停止等待,运行下面的代码
4.互斥体的效率没有临界区高
4.作业:
1.使用临界区的方式:
#include "stdafx.h"
#include<windows.h>
#include"resource.h"
#include<stdio.h>
HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
HWND hEdit4;
HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;
HANDLE g_hMutex;
CRITICAL_SECTION cs;
DWORD WINAPI ThreadProc1(LPVOID lpParameter) ///线程函数1-----------------------------------
{
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
int dwCount=0;
EnterCriticalSection(&cs);
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit2,szBuffer,10); //修改EditText1值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit2,szBuffer);
dwIndex++;
}
LeaveCriticalSection(&cs);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter) ///线程函数2-----------------------------------
{
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
int dwCount=0;
EnterCriticalSection(&cs);
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit3,szBuffer,10); //修改第二功能块值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit3,szBuffer);
dwIndex++;
}
LeaveCriticalSection(&cs);
return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter) ///线程函数2-----------------------------------
{
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
DWORD dwCount=0;
EnterCriticalSection(&cs);
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit4,szBuffer,10); //修改第3功能块值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit4,szBuffer);
dwIndex++;
}
LeaveCriticalSection(&cs);
return 0;
}
DWORD WINAPI ThreadProc4(LPVOID lpParameter)
{
while(1)
{
hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
hThread3=CreateThread(NULL,0,ThreadProc3,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
Sleep(500);
DWORD num=0;
}
CloseHandle(g_hMutex);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg,0);
break;
}
case WM_INITDIALOG:
{
hEdit1 = GetDlgItem(hDlg,IDC_EDIT1);
SetWindowText(hEdit1,"1000");
hEdit2 = GetDlgItem(hDlg,IDC_EDIT2);
SetWindowText(hEdit2,"0");
hEdit3 = GetDlgItem(hDlg,IDC_EDIT3);
SetWindowText(hEdit3,"0");
hEdit4 = GetDlgItem(hDlg,IDC_EDIT4);
SetWindowText(hEdit4,"0");
break;
}
case WM_COMMAND:
{
switch (LOWORD (wParam))
{
case IDC_BUTTON1:
{
HANDLE hThread4=CreateThread(NULL,0,ThreadProc4,NULL,0,NULL);
CloseHandle(hThread4);
return TRUE;
}
}
}
break;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
InitializeCriticalSection(&cs);
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDlgProc);
//Sleep(99999*99999);
return 0;
}
我们要注意,想要循环实现抢红包的功能不可以直接在函数里循环创建线程,因为此时对话框界面还有消息处理函在主线程中,所以必须单独创建一个线程来创建三个线程,不然就会发生线程抢占
2.使用Mutex互斥体的方式:
#include "stdafx.h"
#include<windows.h>
#include"resource.h"
#include<stdio.h>
HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
HWND hEdit4;
HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;
HANDLE g_hMutex;
DWORD WINAPI ThreadProc1(LPVOID lpParameter) ///线程函数1-----------------------------------
{
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
int dwCount=0;
g_hMutex=CreateMutex(NULL,FALSE,"XYZ");
WaitForSingleObject(g_hMutex,-1);
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit2,szBuffer,10); //修改EditText1值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit2,szBuffer);
dwIndex++;
}
ReleaseMutex(g_hMutex);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter) ///线程函数2-----------------------------------
{
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
int dwCount=0;
WaitForSingleObject(g_hMutex,-1);
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit3,szBuffer,10); //修改第二功能块值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit3,szBuffer);
dwIndex++;
}
ReleaseMutex(g_hMutex);
return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter) ///线程函数2-----------------------------------
{
WaitForSingleObject(g_hMutex,-1);
TCHAR szBuffer[10];
memset(szBuffer,0,10);
DWORD dwIndex = 0;
DWORD dwCount=0;
while(dwIndex<50)
{
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
if(dwCount<=50)
{
ExitThread(2);
}
dwCount--;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit1,szBuffer);
memset(szBuffer,0,10);
dwCount=0;
GetWindowText(hEdit4,szBuffer,10); //修改第3功能块值
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit4,szBuffer);
dwIndex++;
}
ReleaseMutex(g_hMutex);
return 0;
}
DWORD WINAPI ThreadProc4(LPVOID lpParameter)
{
while(1)
{
hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
hThread3=CreateThread(NULL,0,ThreadProc3,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hThread3);
Sleep(500);
DWORD num=0;
if(GetExitCodeThread(hThread1,&num)==2 || GetExitCodeThread(hThread2,&num)==2 || GetExitCodeThread(hThread3,&num)==2)
{
ExitThread(3);
}
}
CloseHandle(g_hMutex);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg,0);
break;
}
case WM_INITDIALOG:
{
hEdit1 = GetDlgItem(hDlg,IDC_EDIT1);
SetWindowText(hEdit1,"1000");
hEdit2 = GetDlgItem(hDlg,IDC_EDIT2);
SetWindowText(hEdit2,"0");
hEdit3 = GetDlgItem(hDlg,IDC_EDIT3);
SetWindowText(hEdit3,"0");
hEdit4 = GetDlgItem(hDlg,IDC_EDIT4);
SetWindowText(hEdit4,"0");
break;
}
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDC_BUTTON1:
{
HANDLE hThread4=CreateThread(NULL,0,ThreadProc4,NULL,0,NULL);
CloseHandle(hThread4);
return TRUE;
}
}
break ;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDlgProc);
//Sleep(99999*99999);
return 0;
}