Windows 线程
线程 :
线程由 内核对象 和 线程堆栈 两部分组成 。
内核对象 , 操作系统用它来对线程实施管理。内核对象也是系统用来存放线程统计信息的地方 。
线程堆栈 ,用于维护线程在执行代码时需要的所有函数参数和局部变量 。
线程的整个寿命周期都在进程中 , 线程在它的进程地址空间中执行代码 , 并且在进程的地址空间中对数据进行操作 。如果一个进程中有多个线程 , 那么这些线程将共享单个地址空间 , 这些线程能够执行相同的代码 , 对相同的数据进行操作 , 还能共享内核对象句柄 , 因为句柄表依赖于每个进程而不是每个线程 。
编写第一个线程函数 :
CreateThread 函数 : 创建一个或多个辅助函数 , 只需要让一个已经在运行的线程来调用 CreateThread 函数
HANDLE CreateThread(
PSECURITY_ATTRIBUTES psa , //线程内核对象的默认安全属性 ,可以传递 NULL ,可以传递 SECURITY_ATTRIBUTES 结构体更改安全属性
DWORD cbStack , //用于设定线程可以将多少地址空间用于它自己的堆栈 。
PTHREAD_START_ROUTINE pfnStartAddr , //指明想要新线程执行的线程函数的地址 DWORD WINAPI ThreandFun(PVOID pvParam){return 0;} //函数格式
PVOID pvParam , //新线程要执行函数的实参
DWORD fdwCreate , //设定用于控制创建线程的其他标志 。 0 => 线程创建后立即进行调度 。 CREATE_SUSPENDED => 系统可以完整的创建线程并对它进行初始化 , 但是要暂停该线程的运行 , 这样它就无法进行调度 。
PDWORD pdwThreadID // 使用这个地址来存放系统分配给新线程的 ID
);
当调用 CreateThread 函数时 , 系统创建了一个线程内核对象 。 该线程内核对象不是线程本身 ,而是操作系统用来管理线程的较小的数据结构 。该对象的初始使用计数是 2 。
系统从进程的地址空间中分配内存 , 供线程的堆栈使用 。 新线程的运行环境与创建线程的环境相同 。 因此新线程可以访问进程的内核对象的所有句柄 , 进程中的所有内存和在这个相同的进程中的其他线程的堆栈 。 这使得单个进程中的多个线程确实能够非常容易的互相通信 。
注意 : 如果使用 C/C++ 编写代码 , 那么绝不应该调用 CreateThread 函数创建新的线程 , 应该使用 Visual C++ 运行库函数 _beginthreadex 。
ExitThread 函数 : 线程调用该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源 。但是 C++ 资源(如 C++ 类对象)将不被撤销 。
注意 : 如果使用 C/C++ 编写代码 , 那么绝不应该调用 ExitThread 函数终止线程 , 应该使用 Visual C++ 运行库函数 _endthreadex 。
VOID ExitThread( DWORD dwExitCode ) ;
TerminateThread 函数 : 与 ExitThread 不同 , ExitThread 总是撤销调用的线程 , 而 TerminateThread 能够撤销任何线程 。
BOOL TerminateThread( HANDLE hThread , DWORD dwExitCode );
hThread 参数用于标识被终止运行的线程的句柄 。当线程终止运行时 , 它的退出代码成为你作为 dwExitCode 参数传递的值 。同时 , 线程的内核对象的使用计数也被递减 。
注意 : TerminateThread 函数是异步运行的函数 , 它告诉系统你想要线程终止运行 , 但是 , 当函数返回时 , 不能保证线程已经被撤销 , 如果需要确切的知道该线程已经终止运行 , 必须调用 WaitForSingleObject 函数 , 传递线程的句柄 。
GetExitCodeThread 函数 : 检查线程是否已经终止运行
BOOL GetExitCodeThread( HANDLE hThread , PDWORD pdwExitCode );