多线程程序复习一 2011.05.02
首先最重要的是复习概念:
程序是计算机指令的集合,以文件形式存储在磁盘上。进程是程序在内存中的一个运行实例,是程序在内存中的一次执行活动。所以一个程序可以对应多个进程。进程是线程的执行环境,真正执行代码的线程,所以一个进程至少有一个线程(主线程),一般来说,主线程产生各种子线程,主线程在最后完成执行或者说最后执行各种“关闭”动作。
线程使用进程提供的共享资源实现线程之间的RR轮转法切换(CPU时间片),减少调度切换时间,并发执行。线程栈可以使用系统分配给进程的地址空间,还可以访问进程内核对象中的所有的句柄、进程中的所有内存和在本进程中的其他线程堆栈,所以进程内线程通讯容易实现。
进程由两部分组成的:
①进程内核对象:一个数据结构,只能被内核访问和使用,用于对进程上下文处理、各种计数器处理等信息维护操作。
②地址空间:共有4GB的虚拟内存,其中0~0x7FFFFFFF(2GB)为用户模式的地址,0x80000000~0xFFFFFFFF(2GB)为内核模式的地址,所有进程的内核模式下的内存映射方式相同,供内核代码、设备驱动程序、设备I/O高速缓冲、非页面内存池的分配和进程页面表的使用。
线程由两部分组成的:
①线程内核对象:一个数据结构,用于存放线程切换时候所需要的信息,各种计数器如程序计数器PC(也是IP:Instruction Pointer),执行上下文。
②线程栈:维护线程执行代码时候的函数参数和局部变量。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //SD(NULL:使用默认安全性)
DWORD dwStackSize, // initial stack size(初始化线程堆大小,0:和主线程相同)
LPTHREAD_START_ROUTINE lpStartAddress, // thread function(线程过程函数)
LPVOID lpParameter, //thread argument(用于传入参数)
DWORD dwCreationFlags, //creation option(CREATE_SUSPENDED:挂起;0:正常执行)
LPDWORD lpThreadId // thread identifier(线程ID)
);//从当前线程创建一个子线程,返回一个线程的句柄
BOOL CloseHandle(HANDLE hObject); //关闭句柄,返回0代表失败
DWORD GetLastError(VOID); //获取上一个错误,返回一个Win32 Error Codes
SuspendThread/ResumeThread 挂起和恢复线程传入线程句柄,分别加/减suspend count挂起计数器,返回previous suspend count (这个操作前的suispend count)
Sleep 让当前线程让出参数时间的CPU时间片,就像睡眠了一样呵呵
说说这个suspend count,这是一个计数器,当内核发现suspend count<=0的时候,这个线程就会执行,在创建这个线程的时候使用了CREATE_SUSPENDED参数,suspend count = 1,线程就会被挂起,ResumeThead 能启动挂起的线程,就是因为其能使suspend count - 1,这跟sem和p,v原语一样。
为什么要CloseHandle?在进程内核对象里的线程内核对象使用计数,记录了线程内核使用的情况,创建线程,返回一个线程句柄,这个句柄可以说是线程内核对象的一个引用,所以线程内核对象使用计数为1,当这个计数为0的时候,操作系统才会在线程执行完毕(执行的时候计数可能会增加)去释放线程内核对象。所以,不关闭句柄,即使线程执行完毕(计数为1),其内核对象仍然存在,占用空间,直至整个进程终结了,操作系统才会清除这些残留对象,这明显是不好的。
ExitThread 结束当前的线程,要传如一个ExitCode,线程会做正常的收尾
TerminateThread 终止一个线程,可以在同进程下终止其他线程
注意:这是一个异步执行函数,执行后线程可能不会立刻终结,要用GetExitCodeThread来看线程状态。一旦执行这个函数,程序无法预测线程什么时候被终结,所以目标线程可能没有机会做任何收尾工作,如线程打开的文件或申请的内存没有被释放,系统不会释放被结束的线程的线程栈,如果线程在调用Kernel32.dll里的系统函数时候被强制终止,可能会导致Kernel32处于一个不正确的状态。
ExitProcess 结束当前进程,等于对每一个线程都使用了TerminateThread,可想而知
GetExitCodeThread 获取线程当前的退出码,来确认线程是否退出,若线程还在执行,the exit code is STILL_ACTIVE