线程启动
在进入main函数之前已经启动了线程(mainStartup)
这个线程是进程的主线程,它的入口函数默认的为main/WinMain
该入口函数可以在编译器中进行设置
用CreateThread函数创建线程
在线程创建时会创建线程内核对象,它是一个结构体,不代表线程本身,主要是便于Windows管理
会分配一块线程堆栈空间,每个线程都有自己的堆栈空间
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
);
线程入口函数
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
堆栈大小的设置
通过设置dwStackSize参数来设置线程的堆栈大小
可以设置为0
这样就由编译器来决定堆栈的大小
在VisualStudio中可以进行设置, 默认是 1MB
当线程将自己所拥有的堆栈空间不够用时, 会抛出异常
这个异常会被捕获,再次重新自动重新分配新的栈
线程创建的标志
通过dwCreationFlags来设置线程的运行方式
0
线程立即运行
CREATE_SUSPENDED
暂停状态, 线程不会运行, 除非调用ResumeThread方法
STACK_SIZE_PARAM_IS_A_RESERVATION
表示dwStackSize参数指定的是堆栈的初始保留大小
不指定此标志, dwStackSize将指定堆栈提交大小
线程的抢占式执行
线程的执行是并行的
线程执行的先后顺序是不确定的
可以使用Sleep函数让线程休眠,让出CPU时间片
DWORD WINAPI MyMain(LPVOID lParam)
{
for(int i = 1; i < 101; ++i)
{
printf("%d\n", i);
}
return 0;
}
DWORD WINAPI MyMain1(LPVOID lParam)
{
for (int i = 101; i < 201; ++i)
{
printf("%d\n", i);
}
return 0;
}
int main()
{
int i = -1;
LPVOID lParam = LPVOID(i);
HANDLE hThread[2];
hThread[0] = CreateThread(nullptr, 0, MyMain, lParam, 0, nullptr);
hThread[1] = CreateThread(nullptr, 0, MyMain1, lParam, 0, nullptr);
for (int j = 201; j < 301; ++j)
{
printf("%d\n", j);
}
WaitForMultipleObjects(2, hThread, true, INFINITE);
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
Sleep(100);
return 0;
}