自旋锁和互斥锁实例_多线程编程之自旋锁

一、什么是自旋锁

一直以为自旋锁也是用于多线程互斥的一种锁,原来不是!

自旋锁是专为防止多处理器并发(实现保护共享资源)而引入的一种锁机制。自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋”一词就是因此而得名。自旋锁在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,即在标志寄存器中关闭/打开中断标志位,不需要自旋锁)。

自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。

自旋锁只有在内核可抢占或SMP(多处理器)的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。

二、自旋锁的缺陷

自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,这种锁可能存在两个问题:

(1)死锁。试图递归地获得自旋锁必然会引起死锁:例如递归程序的持有实例在第二个实例循环,以试图获得相同自旋锁时,就不会释放此自旋锁。所以,在递归程序中使用自旋锁应遵守下列策略:递归程序决不能在持有自旋锁时调用它自己,也决不能在递归调用时试图获得相同的自旋锁。此外如果一个进程已经将资源锁定,那么,即使其它申请这个资源的进程不停地疯狂“自旋”,也无法获得资源,从而进入死循环。

(2)过多占用cpu资源。如果不加限制,由于申请者一直在循环等待,因此自旋锁在锁定的时候,如果不成功,不会睡眠,会持续的尝试,单cpu的时候自旋锁会让其它process动不了。因此,一般自旋锁实现会有一个参数限定最多持续尝试次数。超出后,自旋锁放弃当前time slice,等下一次机会。

由此可见,自旋锁比较适用于锁使用者保持锁时间比较短的情况。正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用,而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。

三、Linux环境下的自旋锁

自旋锁的实现基于共享变量。一个线程通过给共享变量设置一个值来获取锁,其他等待线程查询共享变量是否为0来确定锁现是否可用,然后在忙等待的循环中“自旋”直到锁可用为止。自旋锁的状态值为1表示解锁状态,说明有1个资源可用;0或负值表示加锁状态,0说明可用资源数为0。Linux内核为通用自旋锁提供了API函数初始化、测试和设置自旋锁。API函数功能说明如下表所示:

宏定义

功能说明

spin_lock_init(lock)

初始化自旋锁,将自旋锁设置为1,表示有一个资源可用。

spin_is_locked(lock)

如果自旋锁被置为1(未锁),返回0,否则返回1。

spin_unlock_wait(lock)

等待直到自旋锁解锁(为1),返回0;否则返回1。

spin_trylock(lock)

尝试锁上自旋锁(置0),如果原来锁的值为1,返回1,否则返回0。

spin_lock(lock)

循环等待直到自旋锁解锁(置为1),然后,将自旋锁锁上(置为0)。

spin_unlock(lock)

将自旋锁解锁(置为1)。

spin_lock_irqsave(lock, flags)

循环等待直到自旋锁解锁(置为1),然后,将自旋锁锁上(置为0)。关中断,将状态寄存器值存入flags。

spin_unlock_irqrestore(lock, flags)

将自旋锁解锁(置为1)。开中断,将状态寄存器值从flags存入状态寄存器。

spin_lock_irq(lock)

循环等待直到自旋锁解锁(置为1),然后,将自旋锁锁上(置为0)。关中断。

spin_unlock_irq(lock)

将自旋锁解锁(置为1)。开中断。

spin_unlock_bh(lock)

将自旋锁解锁(置为1)。开启底半部的执行。

spin_lock_bh(lock)

循环等待直到自旋锁解锁(置为1),然后,将自旋锁锁上(置为0)。阻止软中断的底半部的执行。

在实际编程中,何时使用spin_lock,何时使用spin_lock_irq呢?这两者有点区别。

(1)spin_lock

spin_lock 的实现关系为:spin_lock -> raw_spin_lock -> _raw_spin_lock -> __raw_spin_lock ,而__raw_spin_lock 的实现为:

static inline void __raw_spin_lock(raw_spinlock_t *lock)

{

preempt_disable();

spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);

}

(2)spin_lock_irq

spin_lock_irq 的实现关系为:spin_lock_irq -> raw_spin_lock_irq -> _raw_spin_lock_irq -> __raw_spin_lock_irq,而__raw_spin_lock_irq 的实现为:

static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)

{

local_irq_disable();

preempt_disable();

spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);

}

由此可见,这两者之间只有一个差别:是否调用local_irq_disable()函数, 即是否禁止本地中断。这两者的区别可以总结为:

在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占。

spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安全的。

举例来说明:进程A中调用了spin_lock(&lock)然后进入临界区,此时来了一个中断(interrupt),该中断也运行在和进程A相同的CPU上,并且在该中断处理程序中恰巧也会spin_lock(&lock)试图获取同一个锁。由于是在同一个CPU上被中断,进程A会被设置为TASK_INTERRUPT状态,中断处理程序无法获得锁,会不停的忙等,由于进程A被设置为中断状态,schedule()进程调度就无法再调度进程A运行,这样就导致了死锁!但是如果该中断处理程序运行在不同的CPU上就不会触发死锁。 因为在不同的CPU上出现中断不会导致进程A的状态被设为TASK_INTERRUPT,只是换出。当中断处理程序忙等被换出后,进程A还是有机会获得CPU,执行并退出临界区。所以在使用spin_lock时要明确知道该锁不会在中断处理程序中使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何卸载symantec

前段时间,业务的虚机上安装了symantec Endpoint Protection(正版), 发现虚机运行一段时间就会失去响应死机,并且有些安装symantec的虚机3389端口无法使用,怎么折腾都不行。最后决定卸载它。一、是否可以用停止服务和终止进程再卸载的方式卸载…

CSS文件引入顺序

<link rel"stylesheet" href"bootstrap.min.css"> <link rel"stylesheet" href"app.css"> 自定义的css要最后引入。因为有时候会修改bootstrap的css。只有后引入的才会覆盖。 如果提前引入了&#xff0c;自定义的会被bo…

浏览器的简单兼容

2019独角兽企业重金招聘Python工程师标准>>> function getXHER() { var xhr null; if(XMLHttpRequest){ xhr new XMLHttpRequest(); }else{ xhr new ActiveXObject(Microsoft.XMLHTTP); } return xhr; }转载于:https://my.oschina.net/u/2511906/blog/1865622

用计算机算出陈赫手机号码,陈赫手机号码遭《快本》曝光,并被网友打到关机!还有人搜到了他的支付宝账户......

原标题&#xff1a;陈赫手机号码遭《快本》曝光&#xff0c;并被网友打到关机&#xff01;还有人搜到了他的支付宝账户...昨天的陈赫可能是被不断的电话铃声叫醒的&#xff0c;因为快本在节目中把陈赫的电话号码给曝光了……当时导演让每个明星向自己的一位圈内好友发出求助短信…

伯努利分布方差_统计分布--深入浅出统计学总结

伯努利分布&#xff1a;一个实验只有两个结果概率发生在{0,1}&#xff0c;发生一个事件成功的概率为 x&#xff0c;不成功的概率为y&#xff0c; 1.若符合伯努基分布条件&#xff1a;p 成功概率 &#xff0c; q 失败概率伯努利分布数学期待&#xff1a;伯努利分布方差&#x…

解决The project description file (.project) for 'xxx' is missing

若没有修改过.project文件&#xff0c;只需重新导入工程即可&#xff0c;别纠结其他的了

macbook禁用键盘_一行命令禁用 MacBook 内置键盘

去年底阿麦换了新的 MacBook Pro&#xff0c;于是她自学生时代就一直在用的老款 MacBook Pro 就归我当玩具了。一度考虑过将其出售&#xff0c;但是想到自己还闲置了一块 SSD&#xff0c;就想着干脆换上让它继续服役。于是买了光驱硬盘支架&#xff0c;想着有时间就给换上。然而…

Java分享笔记:自定义枚举类 使用enum关键字定义枚举类

在JDK1.5之前没有enum关键字&#xff0c;如果想使用枚举类&#xff0c;程序员需要根据Java语言的规则自行设计。从JDK1.5开始&#xff0c;Java语言添加了enum关键字&#xff0c;可以通过该关键字方便地定义枚举类。这种枚举类有自己的程序编写规则&#xff0c;并且具有一些特殊…

html5做咖啡网页素材,HTML5/CSS3咖啡品类切换动画

CSS语言&#xff1a;CSSSCSS确定body {background-color: #FB9F89;}.container {position: absolute;top: 30px;left: 200px;}.saucer {position: absolute;top: 50px;left: 40px;width: 200px;height: 200px;border-radius: 100%;background-color: #FFF;box-shadow: 5px 1px …

汽车和山羊问题matlab仿真_Matlab----无人机集群对抗中的关键问题和仿真平台(开发中)案例...

无人机集群对抗&#xff0c;是自动驾驶中路径规划的新问题&#xff0c;并且连续两年出现在最近的中国大学生数学建模竞赛中。可见&#xff0c;这是一个急需解决的数学问题&#xff08;体现了官方的军事战略意志&#xff09;&#xff0c;同时&#xff0c;还没有成熟解决方案的问…

使用durid的ConfigFilter对数据库密码加密

原文连接&#xff1a;http://blog.csdn.net/aixiaoyang168/article/details/49930513 ----------------------------------------------------------------------- 对于大部分程序员来说&#xff0c;数据库的信息&#xff0c;如用户名&#xff0c;密码等信息一般都写到配置文件…

序(不知道是什么时候的模拟题)

序 【问题背景】 zhx 给他的妹子们排序。 【问题描述】 \(zhx\) 有 \(N\) 个妹子&#xff0c; 他对第 \(i\) 个妹子的好感度为\(a_i\), 且所有\(a_i\),两两不相等。 现在 \(N\) 个妹子随意站成一排&#xff0c; 他要将她们根据好感度从小到大排序。 他使用的是冒泡排序算法&…

html写用户导入,用户基本信息录入.html

&#xfeff;用户基本信息录入$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.…

adg oracle 架构_技术栈数据中心有了ADG架构就高枕无忧了?你还需要做这一步!...

技术栈数据中心有了ADG架构&#xff0c;就高枕无忧了&#xff1f;你还需要做这一步&#xff01;如果把数据中心建设比喻成西天取经&#xff0c;那旅途上的九九八十一难就是我们不得不躲闪、跨越、攻坚的堡垒。即日起&#xff0c;希嘉推出“技术栈”板块&#xff0c;集结数据治理…

String length must be a multiple of four.

今天在整理2013年的工作时的一个项目&#xff0c;修改了数据库连接&#xff0c;初始化数据库&#xff0c;部署运行报错&#xff0c;主要原因是阿里巴巴druid报错&#xff0c;导致DataSource初始化失败。 druid报错日志&#xff1a; Caused by: java.lang.IllegalArgumentExce…

论文笔记:Person Re-identification with Deep Similarity-Guided Graph Neural Network

Person Re-identification with Deep Similarity-Guided Graph Neural Network 2018-07-27 17:41:45 Paper&#xff1a; https://128.84.21.199/pdf/1807.09975.pdf 本文将 Graph Neural Network (GNN) 应用到 person re-ID 的任务中&#xff0c;用于 model 不同 prob-gallery …

CGLib动态代理原理及实现

原文连接&#xff1a;http://songbo-mail-126-com.iteye.com/blog/968792 ------------------------------------------------------------------------ JDK实现动态代理需要实现类通过接口定义业务方法&#xff0c;对于没有接口的类&#xff0c;如何实现动态代理呢&#xff…

微型计算机的硬件组成中ssd硬盘通常是指,2015年计算机一级msoffice选择题121道及答案...

31、通常&#xff0c;在微机中标明的P4或奔腾4是指( D )A、产品型号B、主频C、微机名称D、微处理器型号32、以平均无故障时间(MTBF)&#xff0c;用于描述计算机的( A )A、可靠性B、可维护性C、性能价格比D、以上答案都不对33、以平均修复时间(MTTR)&#xff0c;用于描述计算机的…

双曲函数奇偶性_基本初等函数之奇偶性(强基系列42)

基本初等函数之奇偶性(强基系列4-2)开卷有益初等函数是由幂函数(power function)、指数函数(exponential function)、对数函数(logarithmic function)、三角函数(trigonometric function)、反三角函数(inverse trigonometric function)与常数经过有限次的有理运算(加、减、乘、…

Caused by: Parent package is not defined: json-default - [unknown location]

原文连接&#xff1a;http://blog.csdn.net/bebested/article/details/52627890 ------------------------------------------------------------------------------------------- Unable to load configuration. - [unknown location] at com.opensymphony.xwork2.config.Co…