Windows核心编程:线程调度

来源:互联网 发布:互联网数据是什么 编辑:程序博客网 时间:2024/05/18 06:29

作者:shenzi

链接:http://blog.csdn.net/shenzi

 

Windows核心编程:线程调度
1.线程的挂起和恢复
   
在线程的内核对象中有一个值表示线程的挂起计数。调用CreateProcess或者CreateThread时,系统将创建线程内核对象,并把挂起计数初始化为1。这样,就不会给这个线程调度CPU了。这正是我们所希望的,因为线程初始化需要时间,我们当然不想在线程准备好之前就开始执行它。
   在线程初始化之后,CreateProcess或者CreateThread函数将查看是否有CREATE_SUSPENDED标志传入。如果有,函数返回并让新的线程处于挂起状态。如果没有,函数会将线程的挂起计数递减为0.当线程的挂起计数为0时,线程就成为可调度的了,除非它还在等待某个时间发生(如键盘输入)。
    通过创建一个处于挂起状态的线程,我们可以在线程执行任何代码之前改变它的环境(比如优先级)。改变了线程的环境之后,必须使其变为可调度的。这可以通过ResumeThread函数实现:
    DWORD ResumeThread(HANDLE hThread);

    如果ResumeThread函数成功,它将返回线程的前一个挂起计数;否者,它将返回0xFFFFFFFF。
    除了在创建线程时使用CREATE_SUSPENDED标志外,还可以通过调用SuspendThread来挂起线程:
    
DWORD SuspendThread(HANDLE hThread);

    任何线程都可以调用这个函数挂起另一个线程(只要有线程的句柄)。显然,线程可以将自己挂起,但是它无法自己恢复。与ResumeThread一样,SuspendThread返回线程之前的挂起计数。
    实际开发中,应用程序在调用SuspendThread时必须小心,因为试图挂起一个线程时,我们不知道线程在做什么。例如,如果线程正在分配堆中的内存,线程将锁定堆。当其它线程要访问堆得时候,它们的执行将被中止,直到第一个线程恢复。
2.Sleep函数
    
VOID Sleep(DWORD dwMilliseconds);
    这个函数将使线程自己挂起dwMilliseconds长的时间。关于Sleep,有以下几点只要的事项需要注意:

  • 调用Sleep函数,将使线程自愿放弃属于它的时间片中剩下的部分;
  • 系统设置线程不可调度的时间只是“近似于”锁设定的毫秒数。别忘了,Windows不是实时操作系统;
  • 可以调用Sleep并传入INFINITE。这是告诉系统,永远不要调度这个线程。这样做没有益处,让线程退出并将其栈和内核对象还给系统要好的多;
  • 可以给Sleep传入0。这是在告诉系统,主调线程放弃了时间片的剩余部分,它强制系统调度其它线程。但是,系统有可能重新调度刚刚调用Sleep的那个线程。如果没有系统或者较高优先级的可调度线程时,就会发生这样的事情。   

3.切换到另一个线程
    系统提供了一个名为SwitchToThread的函数,如果存在另一个可调度线程,那么系统会让此线程运行:
    BOOL SwitchToThread();
    调用SwitchToThread与调用Sleep传入0ms类似,区别在于,SwitchToThread允许执行低优先级线程,Sleep会立即重新调度主调线程,即使低优先级线程会处于饥饿状态。

。。。略













原创粉丝点击