一.为什么需要优先级--线程调度的问题

在现实生活中,优先级是一个很常见的现象:在火车站,如果你是孕妇,你是可以走进站中的专门绿色通道的,可以提前上火车以免拥挤;火警119匪警110出警的时候,都是人命关天的大事,是可以优先使用道路的,行人和车辆一律避让;在银行,如果你是白金VIP,也会有专门的绿色通道供你使用.从社会公平层面的优先级,到商业活动中的优先级,大家每天都生活在这样的环境之中,而且是按照这套游戏规则行事。

Windows是一个用户操作系统,在设计上遵循着稳定性为准则,也就是说他要与人类的思维方式保持一致,才能用得舒服,线程的优先级可以说就是这一原则下的产物.如果都让车辆在路上一直依次行驶,那么120到现场的时候,人都可能已经挂了;如果病毒一直抢占CPU,那杀毒软件也就没有什么卵用了。

这里需要注意现实生活中优先级与Windows中优先级的不同之处,现实生活中,我们可以通过新增资源(如增加窗口)优先处理高级别的业务,也可以通过对共同资源的调度(如110出警)来处理优化优先级高的业务。Windows则是在借鉴这些思路的时候进行了自己的一些改造,如调度队列、动态优先级调整等。

二.了解Windows的线程调度

Windows进化到现在,已经是一个时分和抢占式操作系统,它不同于实时操作系统,它通过动态地调整线程等待队列,从而确定线程使用cpu时间片的顺序。优先级高的线程有更大的概率排在队列的前面,同时获得更多数量的时间片,而不是更长时间的时间片。

线程如果被sleep掉、等待io时,会释放他所拥有的cpu,如果线程不是主动释放CPU,线程调度器会抢占该线程。如果优先级相同的多个线程等待使用CPU,则会使用一个循环调度规则来实现队列的先后顺序。

前面我们说过优先级是动态调整的,优先级低的不可能一直都是在等待,随着时间的运转,低优先级线程的优先级会提升,这样线程才有可能在等待结束时获得CPU。

再次强调,线程优先级只是提高了线程被调用的概率,并不是定义CPU调用线程的顺序,具体的工作就交给操作系统内部了。

三.C#中的线程优先级

C#中为我们提供了5个线程优先级别,如下所示:

线程默认的优先级为Normal,可以在线程的运行过程中修改线程的优先级,如下所示:

 static void Main(string[] args)
{
Thread th = new Thread(delegate() { Console.WriteLine("start a new thread"); });
Console.WriteLine(th.Priority);
th.Start();
th.Priority = ThreadPriority.Lowest;
Console.WriteLine(th.Priority);
Console.Read();
}

结果如下:

四.优先级反转

这里要用到锁的知识,对这块有疑问的可以先去大致了解下锁。

假设一种情况,线程A是高优先级线程,线程B是低优先级线程,线程B等啊等,终于等到自己,然后它锁住了一个资源R,然后线程A接手,但是它要用到R,R被锁,然后A只有等待B释放锁,然而B优先级低,它只有经过漫长的等待才能提高自己的优先级得到执行,而此时A仍然在等待B释放锁,从表而看线程A是有非常多的执行机会,但线程A并未执行任何代码,反而B一直在执行,那么线程A何时能够得到资源呢?不知道,原来的优先级设定也就失去了意义。这就是所谓的优先级反转。

那么,如何避免这一问题呢?这里给出一些建议。

1.锁的尺寸应该尽量小,就是使用小锁而非大锁,比如锁定字符串就是一个非常大的锁

2.锁的代码应该尽量短,这样锁定的时间就会尽量少

3.可以使用原子锁

使用优先级继承:也就是,高优先级进程TH在等待低优先级的线程TL占用的竞争资源时,为了使TH能够尽快获得调度运行,由操作系统把TL的优先级提高到TH的优先级,从而让TL以TH的优先级参与调度,尽快让TL执行并释放掉TH欲获得的竞争资源,然后TL的优先级调整到继承前的水平,此时TH可获得竞争资源而继承执行。优先级继承还可以存在传递性,也就是说TL还需要更低的低优先级线程TM的同步资源时,也会把TM的线程优先级拉高到TL,这要看各个操作系统的具体实现。

五.结尾

在做应用程序时,我们建议,尽量不去干预线程的优先级,把调度的顺序交给操作系统处理就好。

六.参考

《C#高级编程(第7版)》

博客  http://blog.csdn.net/feixiaoxing/article/details/7061582

博客  http://blog.csdn.net/thl789/article/details/617629

C#夯实基础之多线程三:线程的优先级的更多相关文章

  1. C#夯实基础之多线程二:主线程、前台线程与后台线程

    我们在<C#夯实基础之多线程一:初识多线程>一文中第二部分中指出,既然windows最终发展出了多线程模型,按理说,我们直接使用一个.NetFramework的线程类就可以直接撸代码了,但 ...

  2. python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  3. [19/04/08-星期一] 多线程_线程的优先级(Priority) 和 守护线程(Daemon)

    一.概念 1. 处于就绪状态的线程,会进入“就绪队列”等待JVM来挑选. 2. 线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5. 3. 使用下列方法获得或设置线程对象的优先级. in ...

  4. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  5. 黑马程序员——JAVA基础之多线程的线程间通讯等

    ------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...

  6. JavaScript夯实基础系列(三):this

      在JavaScript中,函数的每次调用都会拥有一个执行上下文,通过this关键字指向该上下文.函数中的代码在函数定义时不会执行,只有在函数被调用时才执行.函数调用的方式有四种:作为函数调用.作为 ...

  7. Java基础学习——多线程之线程池

    1.线程池介绍     线程池是一种线程使用模式.线程由于具有空闲(eg:等待返回值)和繁忙这种不同状态,当数量过多时其创建.销毁.调度等都会带来开销.线程池维护了多个线程,当分配可并发执行的任务时, ...

  8. java基础之多线程三:多线程并发同步

    由于线程的执行是CPU随机调度的,比如我们开启10个线程,这10个线程并不是同时执行的,而是CPU快速的在这10个线程之间切换执行,由于切换速度极快使我们感觉同时执行罢了. 线程同步问题往往发生在多个 ...

  9. JAVA多线程(三) 线程池和锁的深度化

    github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-servic ...

随机推荐

  1. [网站性能3]SqlServer中Profiler的使用

    原文链接:http://www.cnblogs.com/caishuhua226/p/3838060.html   http://www.cnblogs.com/lyhabc/articles/294 ...

  2. NIO服务器

    导语 NIO的出现是为服务器端编程而设计的.它的作用就是能够让一个线程为多个连接服务.NIO中的API都是非阻塞模式的,这样可以在服务器端采用异步的方式来处理多个请求.NIO中有两个重要的东西就是通道 ...

  3. AngularJS依赖注入

    <html> <head> <meta charset="utf-8"> <title>AngularJS 依赖注入</tit ...

  4. UDP Server

    //UDP服务器端程序,可以接受广播,不可接受多播,多播需要join播地址@Override public void run() { while (true) { try { DatagramSock ...

  5. python基础补漏-01

    python对象的方法 1.python的特性:一切皆对象 2 type(obj) 查看对象的类型 3 dir(obj)查看类中所有详细的功能 4 help(obj) 查看类中所有详细的功能 类中的方 ...

  6. java学习笔记之线程1

    1.线程的概念 线程是系统中最小的执行单元,同一进程有多个线程,多个线程共享进程的资源. 线程调用yield()方法使线程从运行状态转入可运行状态,让出资源: 线程调用sleep()方法使线程由运行状 ...

  7. [bigdata] 使用Redis队列来实现与机器无关的Job提交与执行 (python实现)

    用例场景: 定时从远程多台机器上下载文件存入HDFS中.一开始采用shell 一对一的方式实现,但对于由于网络或者其他原因造成下载失败的任务无法进行重试,且如果某台agent机器down机,将导致它对 ...

  8. TThread.CreateAnonymousThread() 匿名线程对象的应用

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  9. Web API系列(二)接口安全和参数校验

    以前简单介绍过web api 的设计,但是还是有很多朋友问我,如何合理的设计和实现web api.比如,接口安全,异常处理,统一数据返回等问题.所以有必要系统的总结总结 web api 的设计和实现. ...

  10. Oracle 删除重复数据只留一条

    查询及删除重复记录的SQL语句   1.查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断   select * from 表 where Id in (select Id from 表 g ...