IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> rcu入门 -> 正文阅读

[数据结构与算法]rcu入门

是什么

  • 可参考官方文档

  • Read-copy update,可以理解为,先读数据,修改之后,一次性替换旧数据

  • 是linux内核的同步机制,提供线程安全的并发访问

应用场景

  • 典型应用场景
    • 链表
    • 读多写少

实现

链表插入节点

  • 在A之前插入节点,分为3步

在这里插入图片描述

  • 1.new 新节点

  • 2.新节点next指针指向A

  • 3.前置节点的next指针,指向新节点

分析

  • 在2步之后时,所有遍历链表操作正常
  • 在3步之后,所有遍历链表操作也均正常
  • 因为改变指针是原子的,所以不会有问题

链表删除节点

  • 删除B节点,分为3步

在这里插入图片描述

  • A节点的next指针,指向C
  • 等待宽限期过去
  • delete B节点

分析

  • 1步之后,访问到A节点的线程,可以继续访问后续C节点;访问到B节点的线程,可以继续访问C节点
  • 2步,宽限期的含义是,等待所有访问B节点的线程,释放对B节点的访问
  • 3步,当没有线程访问B节点时,可以删除B节点

宽限期详解

  • 写需要加锁
  • 读不需要加锁

参考下面的例子

  • 两个线程,一个读,一个写
  • 假设,当读线程获取gbl_foo之后,线程切换
  • 此时写线程更新gbl_foo,销毁旧gbl_foo
  • 之后,读线程切换回来,发现gbl_foo已经是空指针
 1 struct foo{
 2     int a;
 3     char b;
 4     long c;
 5 };
 6 
 7 DEFINE_SPINLOCK(foo_mutex);
 8 
 9 void foo_read(void)
10 {
11     foo *fp = gbl_foo;
12     if( fp != NULL )
13     {
14         dosomthing(fp->a, fp->b, fp->c);
15     }
16 }
17 
18 void foo_update(foo * new_fp)
19 {
20     spin_lock(&foo_mutex);
21     foo *old_fp = gbl_foo;
22     gbl_foo = new_fp;
23     spin_unlock(&foo_mutex);
24 }

宽限期,即用来解决该问题

  • 写线程更新完gbl_foo之后,调用synchronize_rcu(),阻塞等待至宽限期结束,之后再释放旧指针

  • 读线程加rcu_read_lock()和 rcu_read_unlock(),并不实际加锁,而是进入宽限期

  • synchronize_rcu() 函数需要等待,在此之前所有调用rcu_read_lock() 函数的线程,进行rcu_read_unlock()

    这意味着,所有可能持有旧指针的线程不在使用旧指针

  • 实现上设计复杂的状态机等原理

  • 简单可理解为,rcu_read_lock() 和 rcu_read_unlock()之间不允许线程切换,当synchronize_rcu()之后,CPU都进行至少一次线程切换即可认为宽限期已过

 1 void foo_read(void)
 2 {
 3     rcu_read_lock();
 4     foo *fp = gbl_foo;
 5     if( fp != NULL )
 6         dosomthing(fp->a, fp->b, fp->c);
 7     rcu_read_unlock();
 8 }
 9 
10 void foo_update(foo *new_fp)
11 {
12     spin_lock(&foo_mutex);
13     foo *old_fp = gbl_foo;
14     gbl_foo = new_fp;
15     spin_unlock(&foo_mutex);
16     synchronize_rcu();
17     kfree(old_fp);
18 }
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-15 16:28:07  更:2021-07-15 16:28:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 16:24:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码