网站首页 > 博客文章 正文
一、RCU
RCU,Read-Copy-Update,读复制更新机制。RCU的原理是分成以下几步:
1、无锁的高并发读取
读任务可以无锁的情况下使用RCU临界区(控制读的操作周期),直接操作数据读取,并且不会被写任务阻塞。这个在前面的多线程中,往往区别就在于写会独占操作,防止出现脏数据
2、副本写操作的控制
写任务会拷贝一个数据副本并在其上进行写入操作。完成后,使用原子操作将原数据指针指向此副本,但原数据不会立刻删除,需要等待所有正在使用它的读任务退出临界区后(宽限期)后才能进行回收
3、宽限期
旧数据到替换到所有读者完成读需要的临界区窗口时间,即此时间后,旧数据的内存才会被安全回收。为了提高安全性,可以定义不同的RCU域,用来隔离相关的任务子系统。
二、并行中的应用
并发编程的应用场景有很多,但有一种非常常见的应用场景,就是读多写少的应用场景。比如电商中常见商品说明页面、促销页面及历史购物页面等,上层应用的多线程中的缓存以及分布式共享内存等,内核中的网络堆栈管理、文件系统中的元数据操作等。在这种应用下,在不同的层次上会展开不同层次的处理方式。
那么在内核和上层应用中,就会应用到Read-Copy-Update(RCU)。它作为并发编程中的延迟清理方法,对于增强系统的实时性和稳定性有重要作用。RCU其实并不是一个多么新的概念,在Linux和Folly等库中都有类似的实现。如果有内核开发经验或者使用过相关库及框架的小伙伴们就会深有感触。
RCU,主要就是应用在高频读,低频写。但不适合于内存要求控制严格的场景。
C++标准的发展的一个重要方向就是并行编程,所以为解决并行的技术会不断的增加和完善。而RCU就是C++26为了解决高并场景下的无锁读+非阻塞写的一个解决方案。它通过对旧内存数据的延迟回收及宽限期机制处理来平衡性能和安全。可以简单的理解为将原有的相关的C++上层应用的库或框架中的RCU机制以及内核中的框架机制整合后形成的一个新的标准RCU机制。
它是不是有点无锁编程的味道?对,其实就是这么个意思。所以它也可能产生无锁编程中的ABA问题,所以在标准的实现中,使用了原子指针的替换机制。
三、例程
看一下相关的例程(使用锁和RCU的对比):
//With Reader-Writer Locking
struct Data /* members */ ;
Data* data_; std::atomic data_;
std::shared_mutex m_;
template <typename Func>
Result reader_op(Func fn) {
std::shared_lock<std::shared_mutex> l(m_);
Data* p = data_;
// fn should not block too long or call update()
return fn(p); return fn(p);
}
// May be called concurrently with reader_op
void update(Data* newdata) { void update(Data* newdata) {
Data* olddata;
{
std::unique_lock<std::shared_mutex> wlock(m_);
olddata = std::exchange(data_, newdata);
}
delete olddata; // reclaim *olddata immediately
}
//With RCU in the synchronous style
struct Data /* members */ ;
std::atomic data_;
template <typename Func>
Result reader_op(Func fn) {
std::scoped_lock l(std::rcu_default_domain());
Data* p = data_;
// fn should not block too long or call
// rcu_synchronize(), rcu_barrier(), or
// rcu_retire(), directly or indirectly
return fn(p);
}
// May be called concurrently with reader_op
void update(Data* newdata) {
Data* olddata = data_.exchange(newdata);
std::rcu_synchronize(); // wait until it’s safe
delete olddata; // then reclaim *olddata
}
代码大家只要理解区别就可以,毕竟真实的标准推出还得看最后的结果。不要过于强调代码的实现细节。
四、总结
实践出真知,这个是非常有道理的。没有实际的应用场景的不断的推动。那么技术的发展就会成为无源之水,无本之木。也正是近二十年来互联网特别是移动互联网的高速发展,爆发出了大量的实际应用需求。推动和发展着计算机技术不断的向前演进。而C++语言做为其中一个重要的环节,也为解决这些需求在不断的完善和发展。RCU技术就是其中一个具体的例子。
猜你喜欢
- 2025-08-03 C++语法进阶-字符:字符变量(char)
- 2025-08-03 为什么Linux之父那么讨厌C++ 他骂的这几点。句句扎心
- 2025-08-03 为什么Linux之父那么讨厌C++ 他骂的这几点!句句扎心
- 2025-08-03 20道qiao牛逼的c++/c面试题
- 2025-08-03 C++学习教程_C++语言随到随学_不耽误上班_0基础
- 2025-08-03 20天轻松入门《C++第四章——函数》——4经坛教育
- 2025-08-03 看完侯捷老师所有C++视频之后的总结
- 2025-08-03 C++11+ 泛型编程(模板)
- 2025-08-03 C++20并发库新成员jthread(续)
- 2025-08-03 C++20 四大特性之一:Module 特性详解
你 发表评论:
欢迎- 08-03 Docker 命令入门实战:搞懂这些才算真正入门!
- 08-03Docker 常用命令分类汇总
- 08-03docker常用命令大全,看这一篇就够了
- 08-03Docker命令大全详解(39个常用命令)
- 08-03Docker 常用命令手册
- 08-03Docker命令最全详解(39个最常用命令)
- 08-03Docker命令最全详解(29个最常用命令)
- 08-03C++语法进阶-字符:字符变量(char)
- 最近发表
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- flutterrun (59)
- powershellfor (73)
- messagesource (71)
- plsql64位 (73)
- vueproxytable (64)
- npminstallsave (63)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- nacos启动失败 (64)
- ssh-add (70)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- qcombobox样式表 (68)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)