linux 内核的另一个自旋锁 - 读写锁
除spinlock外,linux 内核还有一个自旋锁,名为arch_rwlock_t。它的头文件是qrwlock.h,包含在spinlock.h,头文件中对它全称为"Queue read/write lock"。这个锁只使用了两个成员变量就实现了读写锁。一个spinlock,以及一个整形锁变量。而spinlock就是这个Queue。
锁的原理是,当没有写意愿或写锁使用时,任意读锁可以并发。当有写意愿或写锁使用时,一切的读锁和写锁都必须进行排队。
arch_rwlock_t的锁变量虽然只是一个整形,但是却是一个压缩的复合数据。它包含了读锁,写锁。
读锁,为锁变量的高24位。只要读锁操作成功对读锁字段加1,就可以获得读锁。
写锁,为锁变量的低8位,包含3种状态,有写意愿,写锁使用中,以及无。
arch_rwlock_t巧妙地将读锁和写锁压缩在一个整形,可以通过原子指令同时对两个锁进行原子操作。不必另外设计一锁对锁变量操作进行保护。
arch_rwlock_t还巧妙地使用了spinlock的自旋和FIFO排队特性,实现了对读写的排队。
arch_rwlock_t的读操作使用atomic_add和atomic_sub支持多个读者对读锁的修改,并且可以与写操作相容。但当上读锁一瞬后发现有写意愿和写进行,就必须归还读锁,进行排队模式。排队的读锁操作,在轮到的时候也不是一步到位就可以成功上读锁。因为这时,有可能其它CPU刚发生的写锁意愿,尽管有其它读写在排队,但这时这个刚发生写锁意愿的CPU是不被排队所约束的。在这种情况下,读锁是不可以归还的,回这会让同样的情况历史重演,使整个排队阻塞不前。所以这个轮到的排队读锁的CPU必须保持这个读锁,直到横刀插入的写锁释放后,马上通行。
reader | rwlock | writer |
1. 从spinlock排队返回 | read == 0 && write state == 0 | |
read == 0 && write state == FF | 1. 刚发起写锁操作,atomic_xchg返回的读锁字段仍为0,OK,没有读锁进行 | |
2. atomic_add返回,发现写锁字段不为0 | read == 1 && write state == FF | 2. 使用写锁 |
3. 自旋等待write state变为0 | ||
read == 1 && write state == 0 | 3. 归还写锁。即使突然发生的写锁操作也不能横刀断入(steal),只好去排队。 | |
4. 马上可以读锁能行。 | ||
5. 释放spinlock,使spinlock排队前进。 | ||
arch_rwlock_t的读操作使用atomic_cmpxchg保证只有一个写者完整进行写锁的修改,并且操作与任意读操作不相容,即有任意读操作同时进行,修改都不被接受。当有写意愿或写锁进行时,所有的写锁操作都必须和读锁操作平等地FIFO排队等候。只有在一个写锁操作发现有读锁进行时,进入排队发出写意愿(修改锁变量的写锁字段),这时候这个写锁操作才会成为第一个排队的操作,优先于其它后继的排队的操作。后继的排队的不论读锁或写锁的操作都是平等的。
spinlock不是用来保护锁变量,而是同步临界区queue_read_lock_slowpath以及queue_write_lock_slowpath的,对有写锁操作参与这一事态,进行对锁操作的排队。
linux 内核的另一个自旋锁 - 读写锁的更多相关文章
- Linux内核的同步机制---自旋锁
自旋锁的思考:http://bbs.chinaunix.net/thread-2333160-1-1.html 近期在看宋宝华的<设备驱动开发具体解释>第二版.看到自旋锁的部分,有些疑惑. ...
- 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊的好同志 | 百篇博客分析OpenHarmony源码 | v26.02
百篇博客系列篇.本篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊的好同志 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊 ...
- 可重入锁 公平锁 读写锁、CLH队列、CLH队列锁、自旋锁、排队自旋锁、MCS锁、CLH锁
1.可重入锁 如果锁具备可重入性,则称作为可重入锁. ========================================== (转)可重入和不可重入 2011-10-04 21:38 这 ...
- Linux内核分析-构造一个简单的Linux系统MenuOS
构造一个简单的Linux系统MenuOS linux内核目录结构 arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel C ...
- Linux 内核:匠心独运之无锁环形队列kfifo
Linux 内核:匠心独运之无锁环形队列 Kernel version Linux 2.6.12 Author Toney Email vip_13031075266@163.com Da ...
- Linux内核分析— —构造一个简单的Linux系统MenuOS(20135213林涵锦)
Linux内核分析— —构造一个简单的Linux系统MenuOS 实验内容 Linux内核的启动过程,从start_kernel到init进程启动 使用实验楼的虚拟机打开shell cd LinuxK ...
- Java并发-显式锁篇【可重入锁+读写锁】
作者:汤圆 个人博客:javalover.cc 前言 在前面并发的开篇,我们介绍过内置锁synchronized: 这节我们再介绍下显式锁Lock 显式锁包括:可重入锁ReentrantLock.读写 ...
- 使用ZooKeeper实现Java跨JVM的分布式锁(读写锁)
一.使用ZooKeeper实现Java跨JVM的分布式锁 二.使用ZooKeeper实现Java跨JVM的分布式锁(优化构思) 三.使用ZooKeeper实现Java跨JVM的分布式锁(读写锁) 读写 ...
- Linux内核RCU(Read Copy Update)锁简析
在非常早曾经,大概是2009年的时候.写过一篇关于Linux RCU锁的文章<RCU锁在linux内核的演变>,如今我承认.那个时候我尽管懂了RCU锁,可是我没有能力用一种非常easy的描 ...
随机推荐
- python中的I/O
先看比较简单的,标准输入输出流 输出到表屏幕: >>>str = "hello, python" >>>print "content: ...
- 设置iPhone网页固定到桌面上的图标
<!--IOS Icon--> <link rel="apple-touch-icon-precomposed" href="@Url.Content( ...
- 浩哥解析MyBatis源码(一)——执行流程
原创作品,可以转载,但是请标注出处地址: 一.MyBatis简介 MyBatis框架是一种轻量级的ORM框架,当下十分流行,配合Spring+Spring MVC组成SSM框架,能够胜任几乎所有的项目 ...
- TIME_WAIT 另一种解决方式 SO_LINGER
被TIME_WAIT问题烦得不行,又发现了另一种解决方式,SO_LINGER. 对SO_LINGER解释最通用的自然是<UNP>,现摘录如下 SO_LINGE ...
- 让我的分页类获取sessionFactory
我们知道在Hibernate里比较重要的sessionFactory,经过Spring的管理可以很好地为Spring里注入使用的bean服务(提供数据源的使用),但是,当我们所要使用的类不是像我们尝试 ...
- node.js 模板 ejs 转
node.js 模板引ejs. 搜了一把推荐用ejs的最多. 速度比对:http://www.cnblogs.com/fengmk2/archive/2011/04/28/2031971.html e ...
- keepalive配置文件详解
第一部分:全局定义块 1.email通知.作用:有故障,发邮件报警. 2.Lvs负载均衡器标识(lvs_id).在一个网络内,它应该是唯一的. 3.花括号“{}”.用来分隔定义块,因此必须成对出现.如 ...
- 视频swiper轮播
关于本次文章的内容,实际上是咪咕阅读详情页中的一个前端需求要做的效果,不过比起原需求,此次案例已经被删减掉许多部分了.音频部分舍弃,调用客户端接口舍弃,并做一些整理.最后留下的是这个精简版的案例.方便 ...
- Android -- 贝塞尔使圆渐变为桃心
1,我们上一篇介绍了贝塞尔曲线推到原理和在Android里的简单使用,今天就和来写写贝塞尔曲线的实际应用,今天实现的效果图如下: 2,思路分析 我们知道首先我们的view是一个圆,这里的圆其实是由四块 ...
- C++实现动态顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构.这样的存储方式使得线性表逻辑上相邻的元素,其在物理存储单元中也是相邻的.只要知道了第一个元素的存 ...