妙啊,阻塞到底是个啥?黄袍加身,亦能谈古说今

本文转载自微信公众号「小姐姐味道」,作者小姐姐养的狗。转载本文请联系小姐姐味道公众号。  

创新互联公司技术团队10多年来致力于为客户提供成都网站制作、成都网站设计、品牌网站制作全网营销推广、搜索引擎SEO优化等服务。经过多年发展,公司拥有经验丰富的技术团队,先后服务、推广了千余家网站,包括各类中小企业、企事单位、高校等机构单位。

现在,请记住你的身份!从进入本篇文章开始,你就是皇帝!三宫六院七十二妃,任君品尝。

人有亲疏远近,事有轻重缓急。作为万岁,你的时间非常宝贵。整个王朝都在你手中运算,方能国泰民安。

为了讨论方便,我们把场景界限在单核CPU上。你就是CPU,当然是仅仅是一颗单核的CPU。

为了让你更好的安排自己的时间,我将你的时间切割成了八九七十二份,每一份都弥足珍贵。

 

就凭我画的这些密密麻麻的小方块,你就应该给xjjdog点下赞。

现实的CPU,时间片分的会更细,但作为人类你是理解不了那么小的时间间隔的:你可能每天都要花很多时间在吃喝拉撒上,但后宫里总有大部分希望得到你宠幸的妃子,你一点时间片都不留给她。

实在是忙不过来呀!需要一个太监!

1. 中断就是从中断掉

不是让太监来帮你干活的,他没有那个能力。太监是用来给你调度工作的。

比如,有反叛的军队攻到了城外,太监慌慌张张来报告,你就不得不暂停后宫的活动,提着裤子处理首要的问题;再比如,有刚来的妃子频频抛媚眼,但你还有一大堆公文要批,心有余而力不足。

这种处理问题的方式,就是中断(从中断掉就是太监)。中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的 CPU 暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。

我们来看下底层的中断处理程序。

 
 
 
 
  1. request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, 
  2.         const char *name, void *dev) 

可以看到,太监只需要给皇帝要做的事情,都编码备案,并固定下处理流程,调整好优先级,皇帝的时间片就可以有效的轮转起来。不至于江山都丢了,还在后宫里风花雪月。

拿网络传输来说,当有了网络数据包,就需要及时处理,否则客户端会超时。这个时候,网卡会立马发出中断请求,CPU就会通过网卡的中断程序去处理这些缓冲区。这都是非常重要的工作。

中断又有硬中断和软中断之分。硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。软中断是由当前正在运行的进程所产生的,通常优先级比硬中断低一些。

2. 阻塞会占用CPU么?

代入了皇帝这个身份,我们就可以解释一些平常遇到的,令人疑惑的问题。

我们都见过在Concurent包下面,有一个叫做LinkedBlockingQeque的类。从它的名字就可以看出,这是一个阻塞队列。实际上,它也并不是挂着羊头卖狗肉。

如下面的代码,我们通常把它放在循环中。我对while(true)这种东西是有心理阴影的,因为它有可能会跑满你的CPU。

 
 
 
 
  1. while(true){ 
  2.    Object o =  linkedBlockingQeque.poll(); 

但实际上,并不会。因为人家都说了,这是个阻塞队列。

相似的,还有NIO中的select。把逻辑放在while循环里,不怕得报应么?

 
 
 
 
  1. while (!stop) { 
  2. int num = selector.select(); 
  3.    if (num == 0) { 
  4.        continue; 
  5.    } 
  6.    Iterator events = selector.selectedKeys().iterator(); 

这还真不怕。因为阻塞并不会占用任何资源。

比如,小太监上报了一个折子,是关于吕嫔妃的舅舅的贪污问题处理。但是这个问题,需要等待司法调查的结果,还需要听听爱妃的意见,就先可以把它搁置在一旁。

把问题记录在一个其他的小册子里,等这些依赖的事办的差不多了,同时你又有龙时,那就可以继续处理。

可以看到,这种阻塞性的问题,虽然是个任务,但并不会占用你的任何时间,这在计算机中是一样的。

我们来看一下常见的Java阻塞方式。

sleep和wait

睡和等。用词很巧妙,到底妙在哪呢?因为它是现实中的场景。

sleep

sleep函数会让线程在一定的时间内进入阻塞状态,不能得到cpu时间,但不会释放锁资源。指定的时间一过,线程重新进入可执行状态。

注意我们这里说的是线程,并不是CPU本身。线程不活动了,并不代表CPU不能干其他事情。

比如,今天是接见大臣的黄道吉日,王天师得到了接见的机会,其他的大臣们就得在外面等着被传唤。结果王天师的谈话又臭又长,勾不起你的任何兴趣。正好小太监急匆匆跑来,在你耳边悄悄说:李贵妃生了个儿子!

这是让人振奋的事情,因为其他儿子都在宫斗中被KO了。于是你装模作样的对王天师说:我现在有点头痛,需要小憩一会儿。” 其实你已经偷偷去探望李贵妃了。

注意,这个时候,王天师只能唯唯诺诺的等着。对于“接见”这个主线来说,其他的大臣也只能在外面等着被传唤。它们都没有拿到“接见”这把锁,王天师也一直占用着这把锁,直到你看完了儿子归来。

这就是sleep不释放锁的意思,因为sleep后,在sleep那一瞬间的任何东西都没有改变。

wait

wait( ) 使线程进入阻塞状态,同时释放自己占有的锁资源,和notify( )搭配使用。

对于wait来说,就完全不一样了。

 

如图,每个监视器(Monitor)在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”。而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。

术语难以理解,还是以皇帝的身份来潇洒一下。

这个时候,你还打算接见大臣。不过,现在不想再one by one了,因为这太低效太枯燥了。某个大臣在你的书房里待得长了些,就有可能有大臣怀疑你在搞gay,这种副作用让人心里不悦。

p2p不行,那就聚在一块谈谈心吧。

正在和你谈话的是王天师,因为这货话比较多,你也比较喜欢他。

王天师说:小太子出生在三伏天,就叫史三伏吧!。

你这才想起自己姓史。作为熟读文章的皇帝,你对此嗤之以鼻,听着这不入流的名字,还隐隐有点生气。

王爱卿,你还是先wait一下吧,听听别人意见。

这个时候,一大堆等着拍马屁的大臣开始举手,跃跃欲试。刘道长抢到了 谈话主线 这把锁。

刘道长: 天地长久,人有终时,北冥有鱼,其名为鲲,可活亿年。我看,就叫史鲲吧。

你听后微微颔首,果然仙人嘴下口水香,但总感觉有点怪异。

注意注意。等着发言的这群大臣,就叫做Entry Set,谁举手举得快,就可以回答这个问题。

像王天师这种被喊停的大臣,就属于Wait Set,只有你重新让他说话,他才有机会。

这整个过程,谈话是可以继续的,并不因为王天师被禁言了谈话就无法进行下去。我们就可以说,wait操作是释放了对象锁的。

计算机中各种所谓的阻塞,都是通过划分不同的队列资源进行处理。比如epoll就是围绕着工作队列和等待队列进行编程的。虽然底层的数据结构有些不同,但思想都是一样的。

线程如何获取时间片?

这个不容易回答,因为你需要知道一个事实:Java中的线程,在Linux上本质是一个轻量级进程,它的调度都是操作系统来完成的。

 

可以看一下我们最上面那一副让人容易产生密集恐惧症的图片。我们的CPU时间,就划分为多个CPU时间片。你的程序虽然在执行while(true),但不代表它总能够得到CPU资源,所以其他的进程也有机会去执行。

JVM采用抢占式调度模型,指的是让优先级高的线程占用比较多的CPU,如果线程优先级相同,那么就随机选择一个线程,使其占用CPU。

注意“随机”这两个字,就非常的有魔性。它可以让你每天都中100万的彩票,也可能每天喝水都被呛着。

可怜的计算机系统,也参与到大千世界让人无奈的随机命运而来。

但有一种很霸道的任务,对CPU一抢一个准,那就是我们上面提到的硬中断--那些不得不优先处理的事情。

下辈子投胎,就当个硬中断吧(囧)。

快来点赞累加你的幸运值吧 :)。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

分享标题:妙啊,阻塞到底是个啥?黄袍加身,亦能谈古说今
网站路径:http://www.shufengxianlan.com/qtweb/news7/294457.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联