当前位置: 首页 > 科技观察

精彩,什么是阻塞?身着黄色长袍,也能说说过去和现在

时间:2023-03-22 10:39:14 科技观察

本文转载自微信公众号“小姐姐的味道”,作者姐姐养的狗。转载本文请联系味觉小姐公众号。现在,请记住你的身份!从你进入本文的那一刻起,你就是皇帝!三宫六院的七十二妃,任君品尝。人有亲疏远近,事有轻重缓急。作为万岁,你的时间很宝贵。整个朝代都掌握在你的手中,国家才能安居乐业。为了讨论方便,我们将场景限制在单核CPU。你是CPU,当然只是单核CPU。为了让你更好的安排时间,我把你的时间切割成了八十九和七十二块,每一块都是宝贵的。就凭我画的密密麻麻的小方块,应该给xjjdog点个赞吧。现实的CPU把时间片划分得更细,但是作为人,你无法理解这么小的时间间隔:你可能每天花很多时间吃喝玩乐,但大多数后宫都想得到你是我的宠妃,一点时间都不留给她。我真的太忙了!我需要太监!1、打断就是中断。又不是太监帮你干活,他没那个本事。太监习惯于为你安排工作。譬如叛军攻入城外,太监仓皇前来禀报,你只得暂停后宫活动,提着裤衩处理主要问题;还有一大堆公文要审批,我的精力比精力还多。这种处理问题的方式就是打断(打断是太监)。中断是指CPU在正常运行过程中,由于内部和外部事件或程序预先安排的事件,CPU暂时停止正在运行的程序,转而转向为内部或外部事件或预先安排的事件服务的程序.完成后返回继续运行暂时中断的程序。让我们看一下低级中断处理程序。request_irq(unsignedintirq,irq_handler_thandler,unsignedlongflags,constchar*name,void*dev)可以看出,太监只需要编码归档给皇帝做什么,并固定处理流程,调整优先级,皇帝的时间片就可以了可以有效旋转。又不是亡国,还在后宫。以网络传输为例,当有网络数据包时,需要及时处理,否则客户端会超时。这时,网卡会立即发出中断请求,CPU会通过网卡的中断程序来处理这些缓冲区。这都是非常重要的工作。中断可分为硬中断和软中断。硬中断是由硬件产生的,如磁盘、网卡、键盘、时钟等。软中断由当前运行的进程产生,通常比硬中断具有更低的优先级。2、阻塞会不会占用CPU?通过代入皇帝的身份,我们可以解释一些我们经常遇到的令人困惑的问题。我们都看到在Concurent这个包下,有一个类叫做LinkedBlockingQeque。从名字就可以看出,这是一个阻塞队列。其实,卖狗肉并不是骗人的把戏。如下面的代码,我们通常把它放在一个循环中。我对while(true)之类的东西有心理阴影,因为它可能会跑满你的CPU。while(true){Objecto=linkedBlockingQeque.poll();}但实际上并没有。因为大家都说过这是一个阻塞队列。同样,NIO中也有select。把逻辑放在while循环里,不怕报复吗?while(!stop){intnum=selector.select();if(num==0){continue;}Iteratorevents=selector.selectedKeys()。iterator();}这真的不可怕。因为阻塞不占用任何资源。比如小太监上报了一张处理吕贵妃舅舅贪污问题的纸条。不过这个问题需要等待司法调查的结果,听取艾菲的意见,暂时可以搁置。把问题记录在不同的小册子里,等依赖的东西差不多做完了,你有龙了,就可以继续搞下去了。可见,这个阻塞问题虽然是一个任务,但是它不会占用你任何的时间,这在计算机中也是一样的。让我们看看常见的Java阻塞方法。睡觉等待睡觉等待。措辞很巧妙,有什么妙处呢?因为那是现实中的场景。sleepsleep函数会让线程进入阻塞状态一段时间,无法获取cpu时间,但不会释放锁资源。一旦指定的时间过去,线程重新进入可执行状态。请注意,我们在这里谈论的是线程,而不是CPU本身。线程处于非活动状态并不意味着CPU不能做其他事情。比如今天是接臣吉日,王天士得到了见面的机会,其他大臣都得在外面等候召见。结果,王天石的谈话又臭又长,没有引起你的兴趣。正好小太监匆匆跑过来,在你耳边低声说:李贵妃生了个儿子!这是一件令人兴奋的事情,因为其他的儿子都在宫斗中被KO了。于是你假装对王天师说:我现在头疼,要睡会儿觉。”其实,你已经暗中拜访过李贵妃了。注意,这个时候,王天师只能乖乖等着。对于‘接见’这一条主线,其他大臣也只能在外面等着被召见了。他们还没有取到“面试”锁,王天石一直占用锁,直到你儿子看完回来。这就是sleep不释放锁的意思,因为sleep之后,sleep的那一刻什么都没有改变。waitwait()让线程进入阻塞状态,同时释放自己拥有的锁资源,与notify()一起使用。对于wait,则完全不同。如图所示,每个监视器(Monitor)在某个时刻,只可以被一个线程拥有,该线程为“ActiveThread”。其他线程为“WaitingThread”,分别在“EntrySet”和“WaitSet”两个队列中等待。在“EntrySet”中等待的线程状态为“Waiting”formonitorentry”,以及在“WaitSet”是“在Object.wait()中”。术语难懂,爽个皇帝吧。这个时候你还打算去见大臣呢。不过,我现在不想一一做,因为这样太没效率也太无聊了。如果一个牧师长时间呆在你的书房里,有些牧师可能会怀疑你是同性恋。这种副作用让人不爽。P2P行不通,大家聚一聚,谈心谈心。和你说话的人是王天石,因为他话多,你更喜欢他。王天师说:小王子是三伏天生的。石三福!你才想起你姓石。作为一个熟悉文章的皇帝,对此嗤之以鼻,听到这个冷门的名字,隐隐有些愤怒。王爱卿,你先等等,听听别人的意见。这时候,不少等着拍马屁的大臣纷纷举起了手,跃跃欲试。刘道长一把抓住了话题的主线锁。刘道长:世界很长,人有尽头。亿万年。在我看来,姑且称之为史坤吧。你闻言微微点头。果然仙人嘴香,但总感觉有些怪怪的。注意。等待发言的群臣称为EntrySet,谁快速举手就可以回答这个问题。像王天士这样被叫停的大臣,属于等候组,只有你再让他说话,他才有机会。在这整个过程中,谈话还能继续,不代表王天石被封禁了,谈话就不能继续了。我们可以说等待操作释放了对象锁。计算机中各种所谓的阻塞,都是通过划分不同的队列资源来处理的。例如,epoll是围绕工作队列和等待队列编程的。虽然底层数据结构有些不同,但是思路是一样的。线程如何获得时间片?这个不好回答,因为你需要知道一个事实:Java中的线程本质上是Linux上的一个轻量级进程,它的调度是由操作系统来完成的。大家可以看看我们上面这张让人容易产生密集恐惧症的图片。我们的CPU时间被分成了多个CPU时间片。虽然你的程序在执行while(true),但并不代表它总能拿到CPU资源,所以其他进程也有机会执行。JVM采用抢占式调度模型,即优先级高的线程占用更多的CPU。如果线程的优先级相同,则随机选择一个线程占用CPU。注意“随机”二字,很神奇。它可以让你每天中100万张彩票,也可以让你天天喝水噎着。可怜的计算机系统也参与了大世界无助的随机命运。但是有一个非常霸道的任务是一个一个抢CPU,那就是我们上面说的硬中断——那些必须先处理的事情。下辈子轮回,就当个硬断吧(囧)。快来点赞累积你的幸运值:)。作者简介:品味小姐姐(xjjdog),一个不允许程序员走弯路的公众号。专注于基础架构和Linux。十年架构,每天百亿流量,与你探讨高并发世界,给你不一样的滋味。我的个人微信xjjdog0,欢迎加好友进一步交流。