一 CreateThread
1. 函数原型:
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
2. 参数说明:
-
第一个参数
lpThreadAttributes
表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。 -
第二个参数
dwStackSize
表示线程栈空间大小。传入0表示使用默认大小(1MB)。 -
第三个参数
lpStartAddress
表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。 -
第四个参数
lpParameter
是传给线程函数的参数。 -
第五个参数
dwCreationFlags
指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。 -
第六个参数
lpThreadId
将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
3.返回值
线程创建成功返回新线程的句柄,失败返回NULL
4.实例
#include <Windows.h>
#include <iostream>
using namespace std;
int n=0;
DWORD WINAPI getMsg(LPVOID lpParam)
{
n++;
cout<<"执行子线程"<<n<<endl;
return 0;
}
int main()
{
int count=5;
while(count--){
DWORD threadID;
HANDLE hThread;
hThread = CreateThread(NULL,0,getMsg,NULL,0,&threadID);
cout<<"执行主线程1!"<<endl;
//Sleep(1);
cout<<"执行主线程2!"<<endl;
}
return 0;
}
输出结果 有多种情况
在多次循环中创建了五个子线程。可以很明显的看出主线程和子线程之间不同步对输出的影响。(换行情况比较混乱)
接下来让情况更加复杂一点。在子线程中继续创建子线程。
#include <Windows.h>
#include <iostream>
using namespace std;
int n=0;
DWORD WINAPI getMsg(LPVOID lpParam)
{
n++;
cout<<"执行子线程"<<n<<endl;
DWORD threadID;
HANDLE hThread;
hThread = CreateThread(NULL,0,getMsg,NULL,0,&threadID);
return 0;
}
int main()
{
int count=5;
while(count--){
DWORD threadID;
HANDLE hThread;
hThread = CreateThread(NULL,0,getMsg,NULL,0,&threadID);
cout<<"执行主线程1!"<<endl;
//Sleep(1);
cout<<"执行主线程2!"<<endl;
}
return 0;
}
依旧可以看出,多个子线程之间不同步造成的影响。
同时多个线程访问临界值n时,因为线程调度的不可控性,导致可能多个线程先后都是从内存上取到的0,这样自加后的结果与实际结果会不一致。为了避免这种情况,就需要原子操作InterlockedExchangeAdd(g_nVal, 1)
LONG InterLockedIncrement(
LPLONG lpAddend // variable address //使++成为原子操作
);
LONG InterlockedDecrement(
LPLONG lpAddend // variable address //使--成为原子操作
);
二.关闭进程
// 结束线程调用,终止自己
VOID WINAPI ExitThread(
__in DWORD dwExitCode // 线程结束时的退出码
);
// 由当前线程终止其他线程
BOOL WINAPI TerminateThread(
__in_out HANDLE hThread, // 终止的线程句柄
__in DWORD dwExitCode // 退出码
);
// 进程退出
VOID WINAPI ExitProcess(
__in UINT uExitCode // 退出码
);
void _endthreadex(
unsigned retval // 退出码
);
_in_out,_in,_out为空宏,不参与编译和运算,仅起到提示作用。