windows多线程编程实现 简单(1)
内容:实现win32下的最基本多线程编程
使用函数:
#CreateThread#
创建线程
HANDLE WINAPI CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadID
);
函数说明:param1 线程内核对象安全属性,一般传入NULL表示使用默认设置
param2 表示线程栈空间大小。传入0,表示默认使用大小1MB
param3 新线程的线程函数地址,多个线程可以使用同一个函数地址
param4 传给线程函数的参数
param5 指定额外的标志来控制线程的创建,为0表示线程创建之后立即可以进行调度,如果为CREATE_SUSPENDED则表示线程创建以后暂停运行,这样无法调度,直到调用ResumeThread()
param6 返回线程的ID号,传入NULL表示不需要返回该线程ID号
注意:尽量使用 _beginthreadex()代替使用CreateThread().标准C运行库与多线程矛盾。
#WaitForMultipleObjects# 同时等待多个对象的触发,也可以用来事件的分别触发,定时触发。 DWORD WaitForMutilpleObjects( DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitALL, DWORD dwMilliseconds, ); 参数 nCount 句柄的最大数 最大值为MAXIMUM_WAIT_OBJECTS 64 HANDLE 句柄数组指针,类型可以为EVENT,Mutex,Process,Thread,Semaphore数组 bWaitAll 等待类型,如果为TRUE,则等待所有信号量再往下执行,FALSE当其中一个信号量有效时就向下执行 dwMilliseconds 超时事件 超时后就执行,如果为WSA_INFINTE永不超时,如果没有信号量就会死在这里。
实现代码:线程IMM_PCentry和Def_DeferredTaskEntry交替运行。本程序并未实现同步,只是简单的多线程操作。
1 #include <windows.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <process.h> 5 6 #define SYN 7 8 int index = 0; 9 HANDLE hMainThread; 10 HANDLE hIMMthread; 11 HANDLE hMainThread_ID = 0; 12 HANDLE hIMMthread_ID = 0; 13 #ifdef SYN 14 HANDLE Mutex_Main; 15 HANDLE Mutex_Imm; 16 #endif 17 18 void WINAPI IMM_PCentry(LPVOID lpParameter) 19 { 20 //WaitForSingleObject(hMutex, INFINITE); //第二个参数为INFINITE表示一直等待,直到拥有互斥对象 21 while (index < 200) 22 { 23 #ifdef SYN 24 WaitForSingleObject(Mutex_Main, INFINITE); 25 #endif 26 index = index + 1; 27 printf("IMM_PCentry hello %d id%d\n", index, hIMMthread_ID); 28 #ifdef SYN 29 SetEvent(Mutex_Imm); 30 #endif 31 } 32 33 } 34 35 void WINAPI Def_DeferredTaskEntry(LPVOID lpParameter) 36 { 37 //WaitForSingleObject(hMutex, INFINITE); //第二个参数为INFINITE表示一直等待,直到拥有互斥对象 38 while (index < 200) 39 { 40 #ifdef SYN 41 WaitForSingleObject(Mutex_Imm, INFINITE); 42 #endif 43 index = index + 1; 44 printf("Def_DeferredTaskEntry hello sharon6 %d id%d\n", index, hMainThread_ID); 45 #ifdef SYN 46 SetEvent(Mutex_Main); 47 #endif 48 } 49 50 } 51 52 int main(void) 53 { 54 #ifdef SYN 55 Mutex_Main = CreateEvent(NULL, 0, 0, NULL); 56 Mutex_Imm = CreateEvent(NULL, 0, 0, NULL); 57 SetEvent(Mutex_Imm); 58 #endif 59 60 hMainThread = CreateThread(NULL, 0, IMM_PCentry, NULL, 0, &hMainThread_ID); 61 hIMMthread = CreateThread(NULL, 0, Def_DeferredTaskEntry, NULL, 0, &hIMMthread_ID); 62 WaitForSingleObject(hMainThread, INFINITE); 63 WaitForSingleObject(hIMMthread, INFINITE); 64 Sleep(200000); 65 CloseHandle(hMainThread); 66 CloseHandle(hIMMthread); 67 return 0; 68 }
未定义#define SYN时打印结果如下
index为两个线程的共享内存变量。
Def_DeferredTaskEntry线程第一次结束后Count = Count + 1 = 1;
IMM_Pcentry线程开始, 执行完 index = index + 1; 线程被Def_DeferredTaskEntry抢占IMM_Pcentry上下文保存了index = 2的值;
Def_DeferredTaskEntry线程开始执行,执行到打印hello 7后,执行到index = index + 1,Def_DeferredTaskEntry线程又被IMM_Pcentry线程抢占,Def_DeferredTaskEntry线程保存线程上下文,包括index = 8;
继续执行上次线程IMM_Pcentry执行的地方,恢复上下文环境,当时保存的是index = 2的值,此时被打印出来。线程IMM_Pcentry继续正常执行。
可以发现,正是因为线程的不断切换,导致index不是每次都加一变化。
为了达到index正常加1的目的,于是利用信号量来实现线程的控制。增加#define SYN宏定义
#CreateEvent# HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes,//安全属性 BOOL bManualReset,//复位方式 BOOL bInitialState,//初始状态 LPCSTR ipName//对象名称 );
#SetEvent# 一种Win32系统编程事件API CEvent::SetEvent BOOL SetEvent(HANDLE hEvent); 其中hEvent表示句柄,返回值;如果操作成功,则返回非零值,否则为0.
可以看到打印结果,两个线程执行顺序得到了控制。注意这里并不是通过加锁来得到想要得结果。