线程基础知识

来源:互联网 发布:志鸿优化系列丛书2016 编辑:程序博客网 时间:2024/06/05 04:35

一、进程由两部分组成,一个是进程内核对象,另一个是地址空间。同样线程也是由两部分组成的:一个是线程的内核对象,另一个是线程堆栈。

二、线程的进入点函数

每个线程必须拥有一个进入点函数,线程从这个进入点开始运行。主线程的进入点函数:即mainwmainWinMainwWinMain。辅助线程的进入点函数的原型:

    DWORD WINAPI ThreadFuncPVOID pvParam);

三、CreateThread函数原型

HANDLE CreateThread

           PSECURITY_ATTRIBUTES psa

           DWORD cbStack

           PTHREAD_START_ROUTINE pfnStartAddr,

           PVOID pvParam,

                   DWORD fdwCreate,

                   PDWORD pdwThreadID);

         注意:尽量使用CreateThread的替代函数。

 

1、   SECURITY_ATTRIBUTES结构:

typedef struct _SECURITY_ATTRIBUTES {

           DWORD nLength

           LPVOID lpSecurityDescriptor

           BOOL bInheritHandle

} SECURITY_ATTRIBUTES

         内核对象能够得到安全描述符的保护。安全描述符用于描述谁创建了该对象,谁能够访问或使用该对象,谁无权访问该对象。

         NULL:默认安全属性。

         bInheritHandle = TRUE:子进程能够继承该线程对象的句柄。

 

2、   cbStack参数用于设定线程可以降多少地址空间用于它自己的堆栈。

可以使用链接程序的/STACK开关来控制这个值:/STACK[reserve] [,commit]

3、   pfnStartAddrpvParam

pfnStartAddr参数用于指明想要新线程执行的线程函数的地址。pvParam参数提供了一个初始化值传递给线程函数,可以是数字值也可以是一个数据结构的指针。

4、   fdwCreate参数可以设定用于控制创建线程的其他标志。只有两个值:0创建后立即调度;CREATE_SUSPENDED暂停该线程的运行。

5、   pdwThreadID用来存放系统分配给新线程的ID。必须是DWORD的一个有效地址。

四、终止线程的运行

l          线程函数返回(最好的方法)

l          调用ExitThread函数,线程将自行撤销(最好不用的方法)

l          同一个进程或另一个进程中的线程调用TerminateThread函数(避免使用的方法)

l          包含线程的进程终止运行(避免使用的方法)

 

线程函数返回:这是确保所有线程资源被正确释放的唯一办法。线程返回做的事项:

l          线程创建的所有C++对象通过他们的撤销函数正确的撤销

l          操作系统将正确地释放线程堆栈使用的内存

l          系统将线程的退出代码设置为线程函数的返回值

l          系统将递减线程内核对象的使用计数

ExitThread函数:VOID ExitThreadDWORD dwExitCode);

该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源将不被撤销。

 

TerminateThread函数:BOOL TerminateThreadHANFDLE hThread DWORD dwExitCode);

该函数是异步运行的函数。

 

五、C/C++运行期库的考虑

若要创建一个新线程,绝对不要调用操作系统的CreateThread函数,必须调用C/C++运行期库函数_beginthreadex

unsigned long _beginthreadex(

           void *security,

           unsigned stack_size,

           unsigned (*start_address)(void *),

           void *arglist,

           unsigned initflag,

           unsigned *thrdaddr);

 

六、线程ID

返回调用线程的进程的伪句柄或线程内核对象的伪句柄:

HANDLE GetCurrentProcess();

HANDLE GetCurrentThread();

 

返回调用线程的进程的唯一ID或它自己的唯一ID

DWORD GetCurrentProcessId();

DWORD GetCurrentThreadId();

 

将伪句柄转换为实句柄:

BOOL DuplicateHandle

           HANDLE hSourceProcess

           HANDLE hSource

           HANDLE hTargetProcess

           PHANDLE phTarget,

           DWORD fdwAccess,

           BOOL bInheritHandle,

           DWORD fdwOptions);

           注意DuplicateHandle会递增特定对象的使用计数,一次完成对复制句柄的使用时,应该将目标句柄传递给CloseHandle,来递减对象的使用计数。

原创粉丝点击