您的位置:首页 > 理论基础 > 数据结构算法

线程基础知识

2008-07-24 15:16 190 查看
一、进程由两部分组成,一个是进程内核对象,另一个是地址空间。同样线程也是由两部分组成的:一个是线程的内核对象,另一个是线程堆栈。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

二、线程的进入点函数

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

    DWORD WINAPI ThreadFunc(PVOID 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、   pfnStartAddr和pvParam

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

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

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

四、终止线程的运行

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

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

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

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

 

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

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

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

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

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

ExitThread函数:VOID ExitThread(DWORD dwExitCode);

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

 

TerminateThread函数:BOOL TerminateThread(HANFDLE 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,来递减对象的使用计数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息