zoukankan      html  css  js  c++  java
  • 无锁编程(六)

    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)); //
    尝试退出临界区,存在冲突则重试

     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    c# -- 实现浏览功能(备忘)
    自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
    爬虫技术 -- 进阶学习(九)使用HtmlAgilityPack获取页面链接(附c#代码及插件下载)
    爬虫技术 -- 进阶学习(八)模拟简单浏览器(附c#代码)
    爬虫技术 -- 进阶学习(七)简单爬虫抓取示例(附c#代码)
    c# -- 介绍File.AppendAllText 方法
    c# -- 解决FromsAuthentication上下文不存在
    c# -- Form1_Load()不被执行的三个解决方法
    爬虫技术 -- 基础学习(六)解析相对地址
    爬虫技术 -- 基础学习(五)解决页面编码识别(附c#代码)
  • 原文地址:https://www.cnblogs.com/linuxbug/p/4840139.html
Copyright © 2011-2022 走看看