您的位置:首页 > 编程语言

Windows 核心编程之6 线程内核对象

2013-08-13 17:28 423 查看
线程内核对象每个进程里,都有一个线程,操作系统用线程内核对象来管理线程。线程有2部分组成:1 线程内核对象。 操作系统来管理线程   2 线程栈, 来存在函数和局部变量的地址空间。什么情况下使用多线程?     当各个任务彼此独立时,可以使用多线程,如:开一个后台线程来检测语法。什么情况下不要使用多线程?      任务联系紧密。如 扫描一个目录的文件,就不适合开多个线程处理,这样处理起来复杂度很高!实现CreateThread 来创建一个线程.如果是C、C++代码的话,使用_beginThreadEx来创建线程为什么? 因为有些C函数里面使用了静态变量,那么多个线程执行的话,会有冲突,但是_beginThreadex做了线程局部处理,它内部就调用了CreateThread函数。WINBASEAPI   表示是winbase.h的API__out_opt       表示是输出HANDLEWINAPICreateThread(    __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,   安全属性,一般为NULL表示默认    __in      SIZE_T dwStackSize,    线程栈的空间,一般使用0来表示默认值    __in      LPTHREAD_START_ROUTINE lpStartAddress,  线程函数地址    __in_opt  LPVOID lpParameter, 线程函数参数    __in      DWORD dwCreationFlags,  创建线程时,指定啥标志 0 表示立即开始执行,CREATE_SUSPENDED 表示暂停    __out_opt LPDWORD lpThreadId   返回线程ID,不需要时,可以传递NULL,表示不关心    );终止运行线程的4种方式:1 线程函数返回(推荐)可以清理C++对象资源,会调用C++的析构函数清理线程栈2 自己调用ExitThread(避免使用)不会调用C++的析构函数清理线程栈如果使用的是C++代码,那么调用_endThreadEx() 来替换ExitThread3 其它线程调用TerminateThread()  避免使用不会调用C++析构函数,也不会清理线程栈ExitThread来结束的线程,会清理堆栈,但是调用terminateThread()函数 不会清理堆栈信息,除非线程所在进程终止。4 线程所在的进程终止                      避免使用C++析构函数不会调用,线程被强行杀死,正常的清理工作没有执行。线程终止时,会发生以下事情:1  线程拥有的所有对象句柄被释放一个线程有2个用户对象: 窗口和挂钩2 退出码有STILL_ACTIVE 变成 ExitThread 或者TerminateThread 返回的退出码3 线程内核对象变成触发状态4 如果线程是最后一个活动线程,那么进程也终止。5 线程内核对象的引用计数减一C和C++库标准的C和C++库,最开始不是为了多线程设计的,在多线程环境下有些函数会出问题:errno,_doserrno, strtok, _wcstok, strerror, _strerror, tmpnam, tmpfile,asctime,gmtime,等所以要不要调用系统的CreateThread,而要调用C,C++运行库 _beginthreadex_beginthreadex 分配和初始化 初始化数据块,并将它与新的线程关联起来_endthreadex  函数 在线程终止运行的 释放分配的数据块不要使用C和C++运行库的这一对函数_beginthread ,_endthread了解自己的身份返回当前进程的句柄  和  IDHANDLE GetCurrentProcess();DWORD GetCurentProceddID();返回当前线程的句柄   和 IDHANDLE GetCurrentThread();DWORD  GetCureentThreadID();注意: 上面这2个函数返回的都是伪句柄伪句柄:表示当前线程的句柄,即调用线程的句柄。下面举一个示例来分析
#include <iostream>
#include <vector>
#include <map>
#include <Windows.h>

#include <tchar.h>
#include <process.h>
#include <Strsafe.h>

HANDLE ghthreadCurrent = NULL;
unsigned int WINAPI ThreadFunc2(LPVOID lp);

unsigned int WINAPI ThreadFunc1(LPVOID lp)
{
HANDLE hThread = GetCurrentThread();

ghthreadCurrent =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hThread, 0, NULL);

while(1)
{
printf("111\n");
Sleep(1000);
}
return 0;
}

unsigned int WINAPI ThreadFunc2(LPVOID lp)
{
HANDLE hThread = (HANDLE)lp;

TerminateThread(hThread,0);

return 0;
}

int main()
{
HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL );

WaitForSingleObject(hThread1,INFINITE);

return 0;
}
线程2 的线程函数 TerminateThread 会把自己杀死,不会杀死线程1使用一个复制句柄的函数 DuplicateHandle() 来复制句柄
#include <iostream>#include <vector>#include <map>#include <Windows.h>#include <tchar.h>#include <process.h>#include <Strsafe.h>unsigned int WINAPI ThreadFunc2(LPVOID lp);unsigned int WINAPI ThreadFunc1(LPVOID lp){HANDLE hThread = GetCurrentThread();HANDLE hTagrealThread = NULL;BOOL bOk = DuplicateHandle(GetCurrentProcess(),hThread,GetCurrentProcess(),&hTagrealThread,0,FALSE,DUPLICATE_SAME_ACCESS);(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hTagrealThread, 0, NULL);while(1){printf("111\n");Sleep(1000);}return 0;}unsigned int WINAPI ThreadFunc2(LPVOID lp){HANDLE hThread = (HANDLE)lp;Sleep(5000);TerminateThread(hThread,0);//必须要关闭句柄CloseHandle(hThread);return 0;}int main(){HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL );WaitForSingleObject(hThread1,INFINITE);CloseHandle(hThread1);printf("main exit\n");system("pause");return 0;}
线程2函数,杀死的是线程1 最后要关闭线程1的线程内核对象复制一个句柄后,线程内核对象引用计数会加1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息