您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

Java白色系列(九):自旋锁 [源码交易]

  • 时间:2022-07-17 00:37 编辑: 来源: 阅读:294
  • 扫一扫,手机访问
摘要:Java白色系列(九):自旋锁 [源码交易]
首先,前言说到“自旋锁”。也许大家会说,有什么好谈的?难道不是等待资源的线程在“打转”吗? 嗯,字面意思很到位,但是能不能具体一点?自旋锁的设计真的那么简单吗?或者这篇文章的作者说了,这个系列的目的是让大家不要停留在表面,而是要深入分析,从而达到:灵活运用的优缺点和原理的掌握。二、锁的优化:当多个线程想同时访问同一个资源时,就会出现资源冲突。这时候大家最直接想到的就是锁互斥访问。锁的时候会出现几个问题:等待资源的线程进入睡眠,客户端状态切换到内核状态,会有一定的性能开销。占用资源的线程很快被用完并释放。此时,等待线程醒来,并立即切换回客户端状态。那么,如果有办法让等待线程短时间等待,可能会有两种结果:等待时间超过这个时间,除了睡觉别无选择;等待时间没有超过,占用资源的线程被释放,那么等待线程就可以直接占用资源。 这是锁的小优化:自旋锁!旋转锁不是真正的锁,而是一个等待它“旋转”并旋转的线程。通常,一个spin的实现非常简单:int SPIN _ LOCK _ NUM = 64int I = 0;布尔wait = true当(wait & amp;amp;amp;amp;(++ I)& lt;SPIN _ LOCK _ NUM);我们通过循环确认的次数来自于旋转。 上一篇文章我们分析小白吧:CAS的时候,有一段JDK源代码:public final class unsafe { public final int getandsetint(object var 1,long var 2,int var 4){ int var 5;do { var 5 = this . getint volatile(var 1,var 2);} while(!this.compareAndSwapInt(var1,var2,var5,var 4));返回var5}}我们可以看到,CAS是自旋锁方法,不断尝试读取volatile修改的最新变量的值,并尝试与期望值进行比较,然后进行升级。 不过这里要注意,既然是无限循环,就要保证占用资源的线程能很快被释放,而不是长时间占用(当然,因为这里的源代码系统也设置了int变量,占用变量的线程很快就会被用完释放)。 三、自旋锁的死锁?怎么会出现僵局?自旋锁虽然好用,但是如果只是停留在上面的分析,还是很肤浅的;虽然自旋锁有很大的优点,但也有很多缺点。除了上述情况之外,原地旋转(忙着等待)总是会消耗CPU资源。同时,还会有一个潜在的可能缺陷:死锁。 3.1.系统中断在讲死锁之前,我们需要了解一下系统中断事件(这一章在高校教材中,ASM汇编中也涉及到系统中断向量表):中断是指在CPU正常运行过程中,CPU因为内部/外部事件,或者程序预先安排的事件而暂停当前工作,从而解决事件,解决事件后再返回继续运行被中断(暂停)的程序。 一般操作系统把中断分为两类:外部中断(硬件中断)和内部中断(异常中断,即软件引起的中断);比如IO设施引起的中断就是硬件中断,比如键盘输入、硬盘/光驱读写等。异常很容易理解,比如NullPointerException。 3.2.中断解析器系统提供了一个API,使我们的程序能够申请注册一个中断解析器(例如,程序接收来自客户的输入事件)。 request _ irq (unsigned int irq,IRQ _ handler _ t handler,unsigned long flags,const char * name,void * dev)参数的含义如下:IRQ:中断号,由系统定义。详情请查看中断向量表。Handler:中断后的ISR(中断服务例程),直接翻译为:中断服务路由;其实就是一个响应中断服务的程序;标志:中断标志;名称:与中断相关的设施的ASCII码,如“keyboard”,这些名称将在/proc/irq和/proc/interrupts中使用;Dev:用于共享中断线路和交付驱动程序的设施结构。 非共享中断直接设置为空中断标志:irqf _ disabled:内核在解这个ISR的过程中禁止其他中断(一般很少使用);IRQF_SAMPLE_RANDOM:表示这个工具产生的中断对内核熵池有贡献;IRQF_TIMER:系统定时器;IRQF_SHARED:多个ISR共享中断线,即一个中断,可以有多个ISR;成功调用request_irq时,返回0,常见错误为-EBUSY,表示给定的中断线路已经在使用中(未指定IRQF_SHARED) 注意:这个函数可能会导致睡眠,所以不允许在中断上下文或者不允许睡眠的程序中使用!在Linux中不需要重新进入中断处理程序。 当一个给定的中断处理程序正在被执行时,断线将在所有的处理程序上被屏蔽,以防止在同一条中断线上接收到另一个新的中断。 通常情况下,除了这个中断之外的所有中断都是开放的,也就是说,其余中断线上的关键点都是可以解决的,但是当前的中断线总是被禁止的,所以同一个中断解决程序绝不会自己嵌套。 这和死锁有什么关系?好了,下一节会讲到。 然而,这里提到的所有中断都是由于我们需要知道的一件事。当系统中断,程序挂起时,程序无法进入睡眠状态。这时候程序只能采取一种方式:自旋,保证不会休眠。 为什么睡不着?这就涉及到“中断上下文”了!3.3.中断上下文如上所述,request_irq可能会导致睡眠,所以不允许在中断上下文中使用。换句话说,中断上下文不允许睡眠!中断上下文:和进程上下文不同,是内核在执行ISR。 ISR没有自己独立的栈,使用内核栈,大小一般有限(32位为8KB)。 同时,ISR中断了正常的程序流程,所以需要保证ISR的执行速度。 因为执行速度快,中断上下文不允许休眠,不允许阻塞!你可能会说执行速度快的时候不允许睡眠。这种解释是不恰当的。我不能睡1ms吗?好了,我们来分析一下失眠的真正原因:当中断解决后,过程切换就不会发生了。 因为唯一能中断当前中断的中断是优先级更高的中断,所以其他进程的优先级不会高于该中断。如果中断上下文是休眠的,是没有办法唤醒的,因为所有的wake_up_xxx都是针对进程的,中断没有进程的概念;只是中断(硬的或软的,不是香烟)都发生在内核中。如果中断上下文休眠,内核就会被阻塞。系统能屏蔽吗?不要!如果被屏蔽,只能重启机器;当调度切换进程时,它将保存当前进程上下文(CPU寄存器值、状态、堆栈SP内容)以供以后恢复和重新操作。 中断发生后,内核保存当前中断进程的上下文。 在ISR中,它是中断上下文。如果它处于休眠或阻塞状态,将调用schedule。保存的流程上下文不是当前流程的上下文,因此无法在ISR中调用schedule。内核中的调度会在进入时判断是否可以在中断上下文中:if(不可能(in _ interrupt()))......崩溃!!!中断处理程序将使用被中断进程的内核堆栈,但对它没有任何影响。由于handler在使用前会被保存,使用后会被清理和恢复;在中断解决的上下文中,内核不能被抢占。如果它休眠了,内核...肯定会被停职。同样,你只能重启机器。所以,被中断的程序也睡不着!然后就只能用“旋转锁”转圈了。 那还是没有说spin为什么会死锁?自旋锁不能递归,否则等待已经获得的锁会导致死锁!一个线程获得了一个自旋锁,在执行过程中被中断处理程序中断,所以线程只是暂停执行,并没有退出,仍然持有自旋锁;然而,中断解析器试图获取自旋锁,但它不能,所以它只能自旋。这就导致ISR无法获得自旋锁,导致自旋无法退出。线程被中断,直到它退出并释放自旋锁才能恢复执行,这导致了死锁和系统崩溃。 4.死锁处理:发生自旋锁死锁。往往由于抢占单个CPU的关键资源,一方持有自旋锁并被中断挂起,而另一方则不断自旋试图获取自旋锁。 所以在多CPU架构下,如果双方分别运行在不同的CPU上,就不会出现死锁。 所以自旋锁有几个重要的特性需要掌握(本质):持有自旋锁的线程(此时必须在临界区)不能休眠,休眠会引起进程切换,CPU被另一个进程占用,无法使用;持有自旋锁的线程不允许被中断,即使是ISR,否则会有ISR自旋;持有自旋锁的线程的内核不能被抢占,否则相当于CPU被抢占;所以根据上面的总结:持有自旋锁的线程不能因为任何原因放弃CPU!所以基于以上问题,spin还需要增加一个上限时间来防止死锁。 linux centos上的自旋锁有三种实现:在单cpu、非抢占式内核中,自旋锁是空的。 在单cpu可抢占内核中,自旋锁被实现为“禁止内核抢占”而不是“自旋”。 (注意)在多cpu、可抢占的内核中,自旋锁实现为“禁止内核抢占”+“自旋”。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)
【技术支持|常见问题】别告诉我你没看过邰方这两则有思想的创意广告! (2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部