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的描 ...
随机推荐
- 菜鸟Scrum敏捷实践系列(一)用户故事概念
菜鸟Scrum敏捷实践系列索引 菜鸟Scrum敏捷实践系列(一)用户故事概念 菜鸟Scrum敏捷实践系列(二)用户故事验收 菜鸟Scrum敏捷实践系列(三)用户故事的组织---功能架构的规划 敏捷开发 ...
- .NET Framework 各版本区别(简介)
本文通过在网络资料整理而得. .NET Framework1.1 1.自带了对mobile asp.net控件的支持.(在1.0版本是以附加功能实现) 2.加入了ASP.NET应用程序的代码安全访问功 ...
- 2.WP8.1开发_在顶部显示标题和进度
有时候加载页面的时候,需要在信号那一栏显示进度,或者把信号栏改成标题 1.确保显示状态栏.默认显示.如果不显示,可以在应用程序启动后手动用代码显示,代码如下: //取得状态栏 StatusBar ba ...
- java学习笔记----数据类型,变量,常量
一.数据类型 1.基本类型(8种,又称内置数据类型).6种数字类型(byte,short,int,long,float,double),一种字符型(char),一种布尔类型(boolean). byt ...
- 判断是否是IE(包含IE11)
判断是否是IE(包含IE11) if(!!window["ActiveXObject"] || "ActiveXObject" in window) { ale ...
- Python之路-计算机基础
一·计算机的组成 一套完整的计算机系统分为:计算机硬件,操作系统,软件. 硬件系统:运算器,控制器和存储器 ,输入设备,输出设备. 1.运算器:负责算数运算和逻辑运算,与控制器一起组成CPU. 2 ...
- 网站建设常用JQuery插件整理
1.jQuery.lazyload 作用:延迟加载网站图片,常用于电商网站.图片展示网站,对于提高网站打开速度比较有效. 2.Owl Carousel 作用:图片滚动特效.响应式传送带插件,特点是支持 ...
- 老李分享:jvm内存原型剖析
老李分享:jvm内存原型剖析 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9088214 ...
- 【CSS/JS学习】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势
引言: 写前端UI的朋友们也许都遇到过这样的问题:我们需要实现这样一个需求,在一个父级元素中隐藏一个可能过长的文本: 这个文本可能是单行的: 也可能是多行的: 下面我就给大家展示如何简单或 ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(七)图片上传功能
日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合>讲了富文本编辑器UEditor的整合与使用 ...