自旋锁/互斥锁/读写锁/递归锁的区别与联系

自旋锁 互斥锁 读写锁 递归锁

 

 

 

互斥锁(mutexlock):

 

最常使用于线程同步的锁;标记用来保证在任一时刻,只能有一个线程访问该对象,同一线程多次加锁操作会造成死锁;临界区和互斥量都可用来实现此锁,通常情况下锁操作失败会将该线程睡眠等待锁释放时被唤醒

自旋锁(spinlock):

同样用来标记只能有一个线程访问该对象,在同一线程多次加锁操作会造成死锁;使用硬件提供的swap指令或test_and_set指令实现;同互斥锁不同的是在锁操作需要等待的时候并不是睡眠等待唤醒,而是循环检测保持者已经释放了锁,这样做的好处是节省了线程从睡眠状态到唤醒之间内核会产生的消耗,在加锁时间短暂的环境下这点会提高很大效率

读写锁(rwlock):

高级别锁,区分读和写,符合条件时允许多个线程访问对象。处于读锁操作时可以允许其他线程和本线程的读锁, 但不允许写锁, 处于写锁时则任何锁操作都会睡眠等待;常见的操作系统会在写锁等待时屏蔽后续的读锁操作以防写锁被无限孤立而等待,在操作系统不支持情况下可以用引用计数加写优先等待来用互斥锁实现。 读写锁适用于大量读少量写的环境,但由于其特殊的逻辑使得其效率相对普通的互斥锁和自旋锁要慢一个数量级;值得注意的一点是按POSIX标准 在线程申请读锁并未释放前本线程申请写锁是成功的,但运行后的逻辑结果是无法预测

递归锁(recursivelock):

严格上讲递归锁只是互斥锁的一个特例,同样只能有一个线程访问该对象,但允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作; windows下的临界区默认是支持递归锁的,而linux下的互斥量则需要设置参数PTHREAD_MUTEX_RECURSIVE_NP,默认则是不支持

大读者锁(brlock-Big Reader Lock)

 

大读者锁是读写锁的高性能版,读者可以非常快地获得锁,但写者获得锁的开销比较大。大读者锁只存在于2.4内核中,在2.6中已经没有这种锁(提醒读者特别注意)。它们的使用与读写锁的使用类似,只是所有的大读者锁都是事先已经定义好的。这种锁适合于读多写少的情况,它在这种情况下远好于读写锁。

大读者锁的实现机制是:每一个大读者锁在所有CPU上都有一个本地读者写者锁,一个读者仅需要获得本地CPU的读者锁,而写者必须获得所有CPU上的锁。

大读者锁的API非常类似于读写锁,只是锁变量为预定义的锁ID。

大内核锁(BKL--Big Kernel Lock)

大内核锁本质上也是自旋锁,但是它又不同于自旋锁,自旋锁是不可以递归获得锁的,因为那样会导致死锁。但大内核锁可以递归获得锁。大内核锁用于保护整个内核,而自旋锁用于保护非常特定的某一共享资源。进程保持大内核锁时可以发生调度,具体实现是:在执行schedule时,schedule将检查进程是否拥有大内核锁,如果有,它将被释放,以致于其它的进程能够获得该锁,而当轮到该进程运行时,再让它重新获得大内核锁。注意在保持自旋锁期间是不运行发生调度的。

需要特别指出,整个内核只有一个大内核锁,其实不难理解,内核只有一个,而大内核锁是保护整个内核的,当然有且只有一个就足够了。

还需要特别指出的是,大内核锁是历史遗留,内核中用的非常少,一般保持该锁的时间较长,因此不提倡使用它。从2.6.11内核起,大内核锁可以通过配置内核使其变得可抢占(自旋锁是不可抢占的),这时它实质上是一个互斥锁,使用信号量实现。

 

RCU(Read-Copy Update)

RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然后对副本进行修改,最后使用一个回调(callback)机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据。这个时机就是所有引用该数据的CPU都退出对共享数据的操作。

RCU也是读写锁的高性能版本,但是它比大读者锁具有更好的扩展性和性能。 RCU既允许多个读者同时访问被保护的数据,又允许多个读者和多个写者同时访问被保护的数据(注意:是否可以有多个写者并行访问取决于写者之间使用的同步机制),读者没有任何同步开销,而写者的同步开销则取决于使用的写者间同步机制。但RCU不能替代读写锁,因为如果写比较多时,对读者的性能提高不能弥补写者导致的损失。

 

顺序锁(seqlock)

顺序锁也是对读写锁的一种优化,对于顺序锁,读者绝不会被写者阻塞,也就说,读者可以在写者对被顺序锁保护的共享资源进行写操作时仍然可以继续读,而不必等待写者完成写操作,写者也不需要等待所有读者完成读操作才去进行写操作。但是,写者与写者之间仍然是互斥的,即如果有写者在进行写操作,其他写者必须自旋在那里,直到写者释放了顺序锁。

这种锁有一个限制,它必须要求被保护的共享资源不含有指针,因为写者可能使得指针失效,但读者如果正要访问该指针,将导致OOPs。

如果读者在读操作期间,写者已经发生了写操作,那么,读者必须重新读取数据,以便确保得到的数据是完整的。

这种锁对于读写同时进行的概率比较小的情况,性能是非常好的,而且它允许读写同时进行,因而更大地提高了并发性。

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

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

相关文章

树莓派安装MySQL数据库与卸载

出处: 1、http://www.cnblogs.com/liyangLife/p/4500115.html 2、https://blog.csdn.net/huayucong/article/details/49736427 3、https://www.imooc.com/article/23132?block_idtuijian_wz 4、http://www.runoob.com/mysql/mysql-install.html(Debian系…

关于selectNodes与selectSingleNode的用法的区别

今天在网上看到一个关于selectNodes与selectSingleNode的用法的区别。 由于之前没有特别在意,因而今日看见是很是惊异。特复制过来,供大家一起学习! 其中文中提到了最重要的区别是在运用操作后的变化。 selectnodes: selectNodes和ChildNo…

第七章 数组

7.1、数组概述 7.1.1、为什么需要数组 答:有时候需要存储或处理一系列数据,数组就可以充当这样的角色,它在内存中是相连的数据,并且在栈中的引用只有一个, 如果不用数组,那数据就得一个一个定义一个一个声明…

notify_one() 或 notify_all() 在c++中的使用要点

notify_one() 或 notify_all() 如果在锁(mutex spin_lock)里调用,可能会导致被立刻唤醒的线程继续阻塞,因为锁被notify线程持有。 c标准上说,一些实现(尤其是许多 pthread 的实现)为了归避这种情况,在通知调用中,直接将…

[转载]Asp.net MVC中Controller返回值类型

Asp.net MVC中Controller返回值类型在mvc中所有的controller类都必须使用"Controller"后缀来命名并且对Action也有一定的要求: 必须是一个public方法必须是实例方法没有标志NonActionAttribute特性的(NoAction)不能被重载必须返回ActionResult类型如: [cs…

Visual Studio.net 2010 Windows Service 开发,安装与调试

本示例完成一个每隔一分钟向C:\log.txt文件写入一条记录为例,讲述一个Windows Service 程序的开发,安装与调试 原程序,加文档示例下载 /Files/zycblog/SourceCode.rar 目录索引 1 开发工具 2 开发过程 3 安装 4 开发调试 5 注意事项 6 参考资料…

ArcGis dbf读写——挂接Excel到属性表 C#

ArcMap提供了挂接Excel表格信息到属性表的功能,但是当数据量较大到以万计甚至十万计的时候这个功能就歇菜了,当然,你可以考虑分段挂接。这个挂接功能只是做了一个表关联,属性记录每个字段的信息需要通过“字段计算器”计算过来。 …

JQuery. Parse XML children recursively. How? - Stack Overflow

JQuery. Parse XML children recursively. How? - Stack OverflowJQuery. Parse XML children recursively. How?

presto领读 查询引擎翻译

原文链接:https://prestodb.io/docs/current/overview/concepts.html#data-sources 最近在看presto-分布式SQL查询引擎的代码,使用翻译工具翻译了一版,有些概念比较难以理解,整理如下: 一、概览 虽然很容易理解语句和…

VisualStudioAddIn2017.vsix的下载安装和使用

本加载项是用于Visual Studio的,下载以后按照如下步骤进行安装: 完全退出Visual Studio把下载了的文件解压缩,会产生一个VisualStudioAddIn2017.vsix文件双击该文件,按照提示安装重启Visual Studio安装完成后的使用方法&#xff0…

Presto基本概念

Presto基本概念 Presto是Facebook开源的MPP SQL引擎,旨在填补Hive在速度和灵活性(对接多种数据源)上的不足。相似的SQL on Hadoop竞品还有Impala和Spark SQL等。这里我们介绍下Presto的基本概念,为后续的笔记做基础。 Operator …

2019春第六周编程总结

这个作业属于哪个课程C语言程序设计Ⅱ这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/MS/homework/2829我在这个课程的目标是利用指针知识解决相关实际问题在具体哪方面帮我实现目标设计密码开锁、交换变量解决问题以及电码加密参考文献C语言基础、http://www.w3scho…

昨天7月21号,笑笑又生病了

21号从上午就开始发烧,中午吃了安瑞克烧退了,但是下午6点左右又开始发烧了,再次吃安瑞克,效果不是太好,还是烧,睡了觉之后烧退了。晚上十点又开始发烧,吃美林悬浮液烧还是没退,又吃安瑞克,还是烧,到了一点钟,烧,但稍微好一点 22号…

Exchange企业实战技巧(26)在Outlook中打开多个邮箱

工作中,有时要需要让某个用户在outlook中同时打开多个exchange邮箱,对于outlook2010来说,是支持多个Exchange邮箱用户账户的并存,而outlook2007则不支持。那该功能有没其他实现方法呢?答案是有的。 如果你的Exchange是…

sql 为什么要用where 1=1或者where 1 =0 ?

一、不用where 11 在多条件查询中的困扰   举个例子,如果您做查询页面,并且,可查询的选项有多个,同时,还让用户自行选择并输入查询关键词,那么,按平时的查询语句的动态构造,代码…

Java元数据总结:Java注释的使用和定义

元数据从metadata一词译来,就是“关于数据的数据”的意思。越来越的开源框架都提供了“元数据”支持了,其实也就是注释支持。今天系统学习一下Java注释(Java元数据)。本文内容不限于Javadoc的注释。  1.什么是Java元数据,有什么作用?  元…

Emulator Error: Could not load OpenGLES emulati...

为什么80%的码农都做不了架构师?>>> 模拟器提示警告:Emulator Error: Could not load OpenGLES emulation library: Could not load DLL! 亲测可用: 从SDK\tools\lib目录下将一下四个dll文件复制到SDK\tools,重启模…

C++中的模板展开问题

在c中使用模板的目的是:减少代码量,相同功能的代码只写一份,根据传入不同的参数,实现相同的功能。 优点:减少了程序开发者的工作 量,只写一份相同功能的代码 缺点:编译器在展开时,每…

请教设计模式大牛们几点

我在做一个3D场景编辑器,假如所有物体从ObjectX而来,现在在此对象层,不知道如何设计出较好的结构来。问题如下: 1:每个物体都可以被单独的设置各种效果——阴影、多重纹理贴图、反射。 也可以设置一些动画&#xff1…

关于.net的垃圾回收和大对象处理_标记

CLR垃圾回收器根据所占空间大小划分对象。大对象和小对象的处理方式有很大区别。比如内存碎片整理 —— 在内存中移动大对象的成本是昂贵的,让我们研究一下垃圾回收器是如何处理大对象的,大对象对程序性能有哪些潜在的影响。 大对象堆和垃圾回收 在.Net …