每隔20ms左右,Windows要查看当前存在的所有线程内核对象。在这些对象中,只有某些对象被视为可以调度的对象。Windows选择可调度的线程内核对象中的一个,将它加载到CPU的寄存器中,它的值是上次保存在线程的环境中的值。这项操作称为上下文转换。

Windows被称为抢占式多线程操作系统,因为一个线程可以随时停止运行,随后另一个线程可进行调度。

暂停和恢复线程的运行

在线程内核对象的内部有一个值,用于指明线程的暂停计数。当调用CreateProcess或

CreateThread函数时,就创建了线程的内核对象,并且它的暂停计数被初始化为1。这可以防止线程被调度到CPU中。

当线程完全初始化好了之后, CreateProcess或CreateThread要查看是否已经传递了

CREATE_ SUSPENDED标志。如果已经传递了这个标志,那么这些函数就返回,同时新线程处于暂停状态。如果尚未传递该标志,那么该函数将线程的暂停计数递减为0。当线程的暂停计数是0的时候,除非线程正在等待其他某种事情的发生,否则该线程就处于可调度状态。

一旦改变了线程的环境,必须使线程成为可调度线程。要进行这项操作,可以调

用ResumeThread。单个线程可以暂停若干次。如果一个线程暂停了3次,它必须恢复3次,然后它才可以被分配给一个CPU。当创建线程时,除了使用CREATE_ SUSPENDED外,也可以调用SuspendThread函数来暂停线程的运行。

在实际环境中,调用SuspendThread时必须小心,因为不知道暂停线程运行时它在进行什么操作。如果线程试图从堆栈中分配内存,那么该线程将在该堆栈上设置一个锁。当其他线程试图访问该堆栈时,这些线程的访问就被停止,直到第一个线程恢复运行。只有确切知道目标线程是什么(或者目标线程正在做什么),并且采取强有力的措施来避免因暂停线程的运行而带来的问题或死锁状态,SuspendThread才是安全的。

暂停和恢复进程的运行

对于Windows来说,不存在暂停或恢复进程的概念,因为进程从来不会被安排获得CPU时间。Windows确实允许一个进程暂停另一个进程中的所有线程的运行,但是从事暂停操作的进程必须是个调试程序。

睡眠方式

线程也能告诉系统,它不想在某个时间段内被调度。这是通过调用Sleep函数来实现的。可以将0传递给Sleep。这将告诉系统,调用线程将释放剩余的时间片,并迫使系统调度另一个线程。但是,系统可以对刚刚调用Sleep的线程重新调度。如果不存在多个拥有相同优先级的可调度线程,就会出现这种情况。

转换到另一个线程

系统提供了一个称为SwithToThread的函数,使得另一个可调度线程。当调用这个函数的时候,系统要查看是否存在一个迫切需要CPU时间的线程。如果没有线程迫切需要CPU时间,SwitchToThread就会立即返回。如果存在一个迫需要CPU时间的线程,SwitchToThread就对该线程进行调度。

调用SwitchToThread函数与调用Sleep是相似的,并且传递给它一个0ms的超时。差别是SwitchToThread允许优先级较低的线程运行。即使低优先级线程迫切需要CPU时间,Sleep也能够立即对调用线程重新进行调度。

线程的运行时间

如果是用GetTickCount的话,即是做了一个简单的假设:它不会被中断。但是,在抢占式操作系统中,永远无法知道线程何时被赋予CPU时间。Windows提供了一个称为GetThreadTimes的函数。它可以返回线程执行操作系统代码和应用程序代码用来多少个100ns的CPU时间。

GetProcessTimes返回的时间适用于某个进程中的所有线程。返回的内核时间是所有进程的线程在内核代码中经过的全部时间的总和。

运用结构环境

环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的CPU时,它就能够找到它上次中断运行的地方。CONTEXT结构中包含了主机C P U上的每个寄存器的数据结构。在x86计算机上,数据成员是Eax、Ebx、Ecx、Edx等等。

Windows实际上允许查看线程内核对象的内部情况,以便抓取它当前的一组CPU寄存器。若要进行这项操作,只需要调用GetThreadContext函数。

在调用GetThreadContext函数之前,应该调用SuspendThread,否则,线程可能被调度,而且线程的环境可能与你收回的不同。一个线程实际上有两个环境。一个是用户方式,一个是内核方式。GetThreadContext只能返回线程的用户方式环境。如果调用SuspendThread来停止线程的运行,但是该线程目前正在用内核方式运行,那么,即使SuspendThread实际上尚未暂停该线程的运行,它的用户方式仍然处于稳定状态。线程在恢复用户方式之前,它无法执行更多的用户方式代码,因此可以放心地将线程视为处于暂停状态, GetThreadContext函数将能正常运行。

Windows使你能够修改CONTEXT结构中的成员,然后通过调用SetThreadContext将新寄存器值放回线程的内核对象中。同样,修改其环境的线程应该首先暂停,否则其结果将无法预测。

实际上,几乎没有应用程序调用这些函数。增加这些函数是为了增强调试程序和其他工具的功能。

线程的优先级

每个线程都会被赋予一个从0(最低)到31(最高)的优先级号码。当系统确定将哪个线程分配给CPU时,它首先观察优先级为31的线程,并以循环方式对它们进行调度。如果优先级为31的线程可以调度,那么就将该线程赋予一个CPU。在该线程的时间片结束时,系统要查看是否还有另一个优先级为31的线程可以运行,如果有,它将允许该线程被赋予一个CPU。只要优先级为31的线程是可调度的,系统就绝对不会将优先级为0到30的线程分配给CPU。

人们可能认为,在这样的系统中,低优先级线程永远得不到机会运行。不过正像前面指出的那样,在任何一个时段内,系统中的大多数线程是不能调度的。

高优先级线程将抢在低优先级线程之前运行,不管低优先级线程正在运行什么。例如,如果一个优先级为5的线程正在运行,系统发现一个高优先级的线程准备要运行,那么系统就会立即暂停低优先级线程的运行(即使它处于它的时间片中),并且将CPU分配给高优先级线程,使它获得一个完整的时间片。

当系统引导时,它会创建一个特殊的线程,称为0页线程。该线程被赋予优先级0,

它是整个系统中唯一的一个在优先级0上运行的线程。当系统中没有任何线程需要执行操作时,0页线程负责将系统中的所有空闲RAM页面置0。

对优先级的抽象说明

• Microsoft没有将调度程序的行为特性完全固定下来。

• Microsoft没有让应用程序充分利用调度程序的特性。

• Microsoft声称调度程序的算法是变化的,在编写代码时应有所准备。

Windows API展示了系统的调度程序上的一个抽象层,这样就永远不会直接与调度程序进行通信。

Windows 支持6个优先级类:即空闲、低于正常、正常、高于正常、高和实时。当然,正常优先级是最常用的优先级类, 99%的应用程序均使用这个优先级类。

当系统什么也不做的时候,将空闲优先级类用于应用程序的运行是最恰当不过的。定期更新系统的某些状态的统计信息跟踪应用程序不应该干扰关键任务的运行。只有当绝对必要的时候,才可以使用高优先级类。Windows Explorer是在高优先级上运行的。大多数时间Explorer的线程是暂停的,等待用户按下操作键或者点击鼠标按钮时被唤醒。如果低优先级线程正在运行,系统会立即抢在这些线程的前面,让Explorer的线程优先运行。MicroSoft就是按这种方法设计Explorer的,因为用户希望无论系统中正在运行什么,外壳程序都具有极强的响应能力。

应该尽可能避免使用实时优先级类。实时优先级是很高的优先级,它可能干扰操作系统任务的运行,因为大多数操作系统线程均以较低的优先级来运行。因此实时线程可能阻止必要的磁盘I/O信息和网络信息的产生。此外,键盘和鼠标输入将无法及时得到处理,用户可能以为系统已经暂停运行。大体来说,必须有足够的理由才能使用实时优先级,比如需要以很短的等待时间来响应硬件事件,或者执行某些不能中断的短期任务。

程序的优先级

创建子进程的进程负责选择子进程运行的优先级类。一旦子进程运行,它就能够通过调用SetPriorityClass来改变它自己的优先级类。

通过将线程的相对优先级与线程的进程优先级类综合起来考虑,系统就可以确定线程的优先级等级。有时这称为线程的基本优先级等级。系统常常要提高线程的优先级等级,以便对窗口消息或读取磁盘等I/O事件作出响应。系统只能为基本优先级等级在1至15之间的线程提高其优先级等级。实际上这是因为这个范围称为动态优先级范围。

当用户对进程的窗口进行操作时,该进程就称为前台进程,所有其他进程则称为后台进程。为了提高前台进程的响应性,Windows能够为前台进程中的线程调整其调度算法。系统可以为前台进程的线程提供比通常多的CPU时间量。这种调整只能在前台进程属于正常优先级类的进程时才能进行。如果它属于其他任何优先级类,就无法进行任何调整。

亲缘性

按照默认设置,当系统将线程分配给处理器时,如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。

计算机在引导时,系统要确定机器中有多少个CPU可供使用。按照默认设置,任何线程都可以调度到这些CPU中的任何一个上去运行。为了限制在可用C P U的子集上运行的单个进程中的线程数量,可以调用SetProcessAffinityMask。子进程可以继承进程的亲缘性。此外,可以使用作业内核对象将一组进程限制在要求的一组CPU上运行。

在大多数环境中,改变线程的亲缘性就会影响调度程序有效地在各个CPU之间移植线程的能力,而这种能力可以最有效地使用CPU时间。

java 线程亲缘性_线程的调度、优先级和亲缘性相关推荐

  1. java executors 详解_线程池—Executors 详解

    各位志同道合的朋友们大家好,我是一个一直在一线互联网踩坑十余年的编码爱好者,现在将我们的各种经验以及架构实战分享出来,如果大家喜欢,就关注我,一起将技术学深学透,我会每一篇分享结束都会预告下一专题 线 ...

  2. java executors 详解_线程池Executors详解

    为什么要用线程池呢? 一是减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务; 二是可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累 ...

  3. java 信号量 互斥锁_线程同步(互斥锁与信号量的作用与区别)

    "信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一 ...

  4. java同步锁售票_线程同步锁之火车站售票案例

    前言: 谈到多线程,就不得不说线程同步,那么什么是线程同步? 线程同步 即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作 ...

  5. java线程池大小_线程池大小设置多少合适?java如何合理设置线程池大小?

    在连接数据库时我们经常会用到线程池,而有时候我们就会烦恼,线程池的大小究竟该设置成多大才合适呢?小伙伴们知道要如何合理设置线程池大小吗?下面跟小编一起来看看吧. 一般来说,我们线程池究竟设置多大是基于 ...

  6. 线程基础知识_线程生命周期_从JVM内存结构看多线程下的共享资源

    线程生命周期 线程状态 New: 线程创建(new Thread()) Runnable: 线程可运行(thread.start()), 注: 调用start并不一定是运行状态, 可能在等待CPU调度 ...

  7. 如何保证线程安全有序性_线程安全性-原子性-可见性-有序性

    一.相关定义: 线程安全类:当多个线程访问某个类时,不管运行环境采用何种调度方式或者这些进程如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安 ...

  8. 线程停止继续_线程不是你想中断就能中断

    这是我2021年的第2篇原创文章,原汁原味的技术之路尽在Jerrycodes 为什么不强制停止 如何用 interrupt 停止线程 sleep 期间能否感受到中断 停止线程的方式有几种 总结 启动线 ...

  9. Linux_多线程(进程与线程的联系_pthread库_线程创建_线程等待_线程正常终止_线程取消_线程分离_pthread_t与LWP)

    文章目录 1.线程的定义,进程和线程的关系 2.Linux下的线程 Linux原生线程库(pthread库pthread.h) 线程的优点 线程的私有数据 3.线程控制 ①创建线程(pthread_c ...

最新文章

  1. Struts2s:select/s:select
  2. win10系统使用Anaconda安装opencv(python)
  3. ajax请求 apend,jsp如何获取ajax append的数据?
  4. mac删除android sd卡,如何从mac完全删除android及其所有文件?
  5. Android的HTTP方式网络通信---HttpURLConnection
  6. 力扣78. 子集(JavaScript)
  7. 交流:Ghost版系统安装简单分析
  8. 安卓怎么把一个按钮设计成梯形_常闭触点输入信号处理的电路图及PLC梯形图
  9. 苹果Mac电脑配置flutter开发环境
  10. jquery视频教程(jquery视频教程全集)
  11. Wincc安装教程+破解教程(包括软件下载链接——百度网盘)
  12. mysql数据库——思维导图
  13. 怎样制作CHM格式的电子书?
  14. JAWS模块分析(小东子)
  15. adb shell cmd appops
  16. 150本畅销书已选好,快来认领!!
  17. Bootstrap学习文档(三)
  18. ubuntu 建立光纤连接
  19. C 语言管理个人财务系统
  20. 《UnityAPI.AudioClip音频剪辑》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+AudioClip+loadInBackground+立钻哥哥++OK++)

热门文章

  1. 机械图样解读——螺旋线与螺旋面
  2. 淮北计算机考试报名,2021年9月淮北市计算机二级报名时间|网上报名入口【7月2日9点开通】...
  3. 物流运输行业商业供应商管理平台:优化供应链关系,助力企业进入数字化快车道
  4. 苹果4s怎么越狱教程_苹果手机桌面图标怎么随意摆放 iPhone桌面图标随意摆放教程...
  5. js文件流,导出txt
  6. 由浪潮大型机M13说开去
  7. 批量备案域名查询工具-批量备案域名扫描查询
  8. 解密Kotlin 1.6.20 新功能 Context Receivers
  9. 调用smooth函数进行加噪数据的平滑处理
  10. 阴阳师人数最多的服务器,说说阴阳师中玩家最少的几个鬼区服务器