无锁编程(六) - seqlock(顺序锁)
seqlock(顺序锁)
用于能够区分读与写的场合,并且是读操作很多、写操作很少,写操作的优先权大于读操作。
seqlock的实现思路是,用一个递增的整型数表示sequence。写操作进入临界区时,sequence++;退出临界区时,sequence再++。写操作还需要获得一个锁(比如mutex),这个锁仅用于写写互斥,以保证同一时间最多只有一个正在进行的写操作。
当sequence为奇数时,表示有写操作正在进行,这时读操作要进入临界区需要等待,直到sequence变为偶数。读操作进入临界区时,需要记录下当前sequence的值,等它退出临界区的时候用记录的sequence与当前sequence做比较,不相等则表示在读操作进入临界区期间发生了写操作,这时候读操作读到的东西是无效的,需要返回重试。
seqlock写写是必须要互斥的。但是seqlock的应用场景本身就是读多写少的情况,写冲突的概率是很低的。所以这里的写写互斥基本上不会有什么性能损失。
而读写操作是不需要互斥的。seqlock的应用场景是写操作优先于读操作,对于写操作来说,几乎是没有阻塞的(除非发生写写冲突这一小概率事件),只需要做sequence++这一附加动作。而读操作也不需要阻塞,只是当发现读写冲突时需要retry。
seqlock的一个典型应用是时钟的更新,系统中每1毫秒会有一个时钟中断,相应的中断处理程序会更新时钟(写操作)。而用户程序可以调用gettimeofday之类的系统调用来获取当前时间(读操作)。在这种情况下,使用seqlock可以避免过多的gettimeofday系统调用把中断处理程序给阻塞了(如果使用读写锁,而不用seqlock的话就会这样)。中断处理程序总是优先的,而如果gettimeofday系统调用与之冲突了,那用户程序多等等也无妨。
seqlock的实现非常简单:
写操作进入临界区时:
void write_seqlock(seqlock_t *sl)
{
spin_lock(&sl->lock); // 上写写互斥锁
++sl->sequence; // sequence++
}
写操作退出临界区时:
void write_sequnlock(seqlock_t *sl)
{
sl->sequence++; // sequence再++
spin_unlock(&sl->lock); // 释放写写互斥锁
}
读操作进入临界区时:
unsigned read_seqbegin(const seqlock_t *sl)
{
unsigned ret;
repeat:
ret = sl->sequence; // 读sequence值
if (unlikely(ret & 1)) { //
如果sequence为奇数自旋等待
goto repeat;
}
return ret;
}
读操作尝试退出临界区时:
int read_seqretry(const seqlock_t *sl, unsigned start)
{
return (sl->sequence != start); //看看sequence与进入临界区时是否发生过改变
}
而读操作一般会这样进行:
do {
seq = read_seqbegin(&seq_lock);// 进入临界区
do_something();
} while (read_seqretry(&seq_lock, seq)); // 尝试退出临界区,存在冲突则重试
版权声明:本文为博主原创文章,未经博主允许不得转载。
无锁编程(六) - seqlock(顺序锁)的更多相关文章
- C++性能榨汁机之无锁编程
C++性能榨汁机之无锁编程 来源 http://irootlee.com/juicer_lock_free/ 前言 私以为个人的技术水平应该是一个螺旋式上升的过程:先从书本去了解一个大概,然后在实践中 ...
- linux内核同步之信号量、顺序锁、RCU、完成量、关闭中断【转】
转自:http://blog.csdn.net/goodluckwhh/article/details/9006065 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一信 ...
- [转]透过 Linux 内核看无锁编程
非阻塞型同步 (Non-blocking Synchronization) 简介 如何正确有效的保护共享数据是编写并行程序必须面临的一个难题,通常的手段就是同步.同步可分为阻塞型同步(Blocking ...
- 海量并发的无锁编程 (lock free programming)
最近在做在线架构的实现,在线架构和离线架构近线架构最大的区别是服务质量(SLA,Service Level Agreement,SLA 99.99代表10K的请求最多一次失败或者超时)和延时.而离线架 ...
- C++11原子操作与无锁编程(转)
不讲语言特性,只从工程角度出发,个人觉得C++标准委员会在C++11中对多线程库的引入是有史以来做得最人道的一件事:今天我将就C++11多线程中的atomic原子操作展开讨论:比较互斥锁,自旋锁(sp ...
- 无锁编程以及CAS
无锁编程 / lock-free / 非阻塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Sy ...
- 无锁编程(一) - Double-checked Locking
Double-checked Locking,严格意义上来讲不属于无锁范畴,无论什么时候当临界区中的代码仅仅需要加锁一次,同时当其获取锁的时候必须是线程安全的,此时就可以利用 Double-che ...
- 4.锁--无锁编程以及CAS
无锁编程以及CAS 无锁编程 / lock-free / 非堵塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被堵塞的情况下实现变量的同步,所以也叫非堵塞同步(Non-b ...
- 无锁编程 - Double-checked Locking
Double-checked Locking,严格意义上来讲不属于无锁范畴,无论什么时候当临界区中的代码仅仅需要加锁一次,同时当其获取锁的时候必须是线程安全的,此时就可以利用 Double-check ...
随机推荐
- windows 上配置solr5.2.1+solr4.3+中文分词器
搭建5.2.1 1.下载 Tomcat解压后的目录为 D:\Program Files\Apache Software Foundation\apache-tomcat-8.0.22 solr解压后的 ...
- JavaScript之arguments对象讲解
javascript的arguments对象类似于PHP的extract()函数实现. 在不确定函数参数个数的情况下,可以通过arguments访问参数,并以索引0为起始. function sayH ...
- GCD创建一个单例
1.+(id)shareInstance{ static ClassA *A=nil; static dispatch_once_t onceToken; dispatch_once(&onc ...
- 1303: [CQOI2009]中位数图
早起一AC,整天萌萌哒. Problem: 1303 User: forgot93 Language: C++ Result: Accepted Time:56 ms Memory:2108 kb * ...
- Unity上使用Linq To XML
using UnityEngine; using System.Collections; using System.Linq; using System.Xml.Linq; using System; ...
- Linuxshell脚本之if条件判断
IF条件判断 .基本语法: if [ command ]; then 符合该条件执行的语句 fi .扩展语法: if [ command ];then 符合该条件执行的语句 elif [ comman ...
- Android的Testing和Instrumentation
Android提供了一系列强大的测试工具,它针对Android的环境,扩展了业内标准的JUnit测试框架.尽管你可以使用JUnit测试Android工程,但Android工具允许你为应用程序的各个方面 ...
- Mybatis批量插入oracle,mysql
oracle <insert id="addUserData" parameterType="java.util.List"> INSERT IN ...
- 数据库中已存在名为 'View_Business' 的对象。
用EF框架+MCF,编译的时候出现:数据库中已存在名为 'View_Business' 的对象. 解决方案: 1.Enable-Migrations2.Add-Migration3.Update-Da ...
- **app后端设计(10)--数据增量更新(省流量)
在新浪微博的app中,从别的页面进入主页,在没有网络的情况下,首页中的已经收到的微博还是能显示的,这显然是把相关的数据存储在app本地. 使用数据的app本地存储,能减少网络的流量,同时极大提高了用户 ...