并发编程3. 线程的高级内容 20131031
前面讲解了线程的创建退出知识,但是对于线程的高级内容,比如线程的各种状态、操作系统中线程调度的方式,如何控制线程的执行,等等线程的高级内容没有深入的了解,这一章会重点介绍。
1.线程的状态
硬件中栈的起始地址是大于结束地址的,随着线程中使用的空间越来越多,栈指针(位域ESP寄存中)的值也会相应的递减。编译器通常会借助线程栈来实现函数调用以及存储一些无法在存储器中保存的数据。
栈的保留大小与提交大小
线程栈大小包括两个部分,一个是保留大小(Reserve Size ) 一个是提交大小(Commit Size)。程序分配内存的时候,可以预先保留一定数量的内存,但程序需要的写入这些内存的时候在提交它们。
2.线程的创建和初始化过程
创建线程:
1)分配一些重要的线程数据结构,比如KTHREAD, ETHREAD等内容,还将初始化一些结构用于异步过程调用,本地过程调用,内存管理,IO等等,之后生成一个唯一的线程ID。
2)分配线程上下文环境:其中包含了特定于CPU的寄存器信息,这会生成一个CONTEXT数据结构,他将在随后的上下文切换期间用于捕获和恢复处理器的状态,可以通过GetUserContext来访问该信息。或者是
BOOL GetThreadContext(HANDLE hThread, LPCONTEXT lpContext) ;
3)创建进程地址空间的用户态栈,创建和初始化内核态栈。
4)Windows子系统进程CSRSS.exe将会收到创建线程的通知,此时可以记录一下在初始化线程状态和执行线程的信息。
5)进程的第一个线程在执行线程起始执行函数之前就必须完成进程的初始化工作,包括加载DLL,初始化系统服务等等。
6)将DLL_THRTEAD_ATTACH 通知发送给进程中所有的DLL
7)如果线程中没有设置CREATE_SUAPENDED,线程立即执行,使用Windows线程调度器调度线程。
8)线程创建函数返回,返回的是线程的HANDLE,出口参数线程ID设置为分配给这个线程的唯一标志符。
线程终止:线程的内存对象被设置成为已经触发的状态,触发线程对象意味着你可以像其他Win32同步事件那样,来使用线程的句柄;释放用户态栈,强行结束的线程中的用户态栈,将会在进程结束的时候释放;所有的内核态数据结构,包括栈、上下文,TEB,TLS等等与线程相关的内存数据结构都将被释放。
3.线程调度的知识
Windows线程都有优先级,Windows线程调度器是基于优先级来工作的,调度器的基本单位是线程而不是进程。
进程线程的优先级:
BOOL WINAPI SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);
DWORD WINAPI GetPriorityClass(HANDLE hProcess);
BOOL WINAPI SetThreadPriority(HANDLE hThread, int priority);
int WINAPI GetThreadPriority(HANDLE hThread);
线程睡眠与退让
VOID WINAPI Sleep(DWORD dwMilliSeconds);
DWORD WINAPI SleepEx(DWORD dwMilliSeconds, BOOL bAlertable);
BOOL WINAPI SwitchToThread();
线程挂起:
DWORD WINAPI SuspendThread(HANDLE hThread);
DWORD WINAPI ResumeThread(HANDLE hThread);
线程挂起是不会释放资源的锁的,所以如果线程A挂起了线程B,而且线程B持有一个对象的lock,但是B被挂起之后是不会释放资源的锁的,这样A线程是无法获取指定对象的锁,出现死锁。
追梦的飞飞
于广州中山大学图书馆 20131031
HomePage: http://yangtengfei.duapp.com