01. 非阻塞的Skiplist

news/2025/3/18 6:55:17/文章来源:https://www.cnblogs.com/lang77/p/18778127

首先学习LevelDB当中比较独立的一部分,当然的,读源码的话,一个很好的入门的感觉就是先从一个独立的组件模块开始,一个比较容易的开始,SkipList

然后跳表的基本概念什么的我不太想要去过多的赘述,就像二叉树那样希望能得到log(N)的性能,而又利用概率算法更好实现,可以看leveldb-handbook:内存数据库

读写特性

LevelDB的实现中,主要就是实现

  • PUTGET两个接口
  • 特性是它的GET 操作非阻塞的特性
  • 写写冲突是需要external sync来实现,在一个时间下只有一个写可以执行来实现线程安全的机制

这样为了实现读写冲突不加锁的性质,主要实现的思想就是

  • 首先在跳表的不同层高中插入节点这一个操作是原子的
  • 插入的顺序是从最底层开始向上传递的

这样可以实现在GET操作中,即使在GET上方没有能找到对应的节点,但是它会向下走,到最后一层就一定会看见,即使中间没有看见

实现细节

在实现上就是有一个虚拟头节点Node* const head_; 这个节点拥有最高的层高,然后本身节点是NULL,然后为了保证"跳表的不同层高中插入节点这一个操作是原子的", 对Struct Node的实现中std::atomic<Node*> next_[1];存储next的指针是atomic的类型,对其读写使用std::memory_order_acquire, std::memory_order_release来实现原子性和防止重排序

跳表

然后,重点不是说能完全说会它的实现,然后每一个细节都不放过,没有,重点是理解跳表是如何实现它的乐观读写特性,以及实现上对atomicstd::memory_order_acquire, std::memory_order_release的使用

tips: 哦,对了,这个跳表并不支持删除,所谓的删除它还是使用Put然后插入一个空值,还没有完全地理解这个

SkipList 内部的 Node 实现

template <typename Key, class Comparator>
struct SkipList<Key, Comparator>::Node {explicit Node(const Key& k) : key(k) {}Key const key;Node* Next(int n) {assert(n >= 0);return next_[n].load(std::memory_order_acquire); // 1.}void SetNext(int n, Node* x) {assert(n >= 0);next[n].store(std::memory_order_release); // 2.}// No-barrier variants that can be safely used in a few locations ...private:std::atomic<Node*> next_[1];
};

SkipList 的 insert 方法

template <typename Key, class Comparator>
void SkipList<Key, Comparator>::Insert(const Key& key) {Node* prev[kMaxHeight];Node* x = FindGreaterOrEqual(key, prev);// Not allow duplicate insertionassert(x == nullptr || !Equal(key, x->key));int height = RandomeHeight();if (height > GetMaxHeight()) {  // 超出MaxHeight的部分使用head_for (int i = GetMaxHeight(); i < height; i ++) {prev[i] = head_;}// 对max_height的修改可以没有什么同步要求max_height_.store(height, std::memory_order_relaxed);}x = NewNode(key, height);for (int i = 0; i < height; i ++) {// 在这里使用NoBarrier读是可以的因为只有这一个在写,noBarrier写也ok// 因为后面对prev[i]设置的时候是会有屏障的,能保证在prev.SetNext的时候// x的next是设置好了的x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));// 重点就是维持两种一致性:// (1) 保证在加入到SkipList的时候next指针已经指向后面的// (2) 保证如果上层看见了的话,下层一定要存在prev[i]->SetNext(i, x); }
}

SkipList 的 Contain 方法

template<typename Key, class Comparator>
bool SkipList<Key, Comparator>::Contains(const Key& key) const {Node* x = FindGreaterOrEqual(key, nullptr); // 看是否存在,level0if (x != nullptr && Equal(key, x->key)) {return true;} else {return false;}
}

SkipList 帮助方法 FindGreaterOrEqual

template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node* 
SkipList<Key, Comparator>::FindGreaterOrEqual(const Key& key, Node** prev) const {Node* x = head_;int level = GetMaxHeight() - 1;while (true) {Node* next = x->Next(level);if (KeyIsAfterNode(key, next)) {  // Keep searching in this levelx = next;} else /* next->key 大于或者等于 key */ {  if (prev != nullptr) prev[level] = x; // 于是 x 就是最后一个小于 key 的节点if (level == 0) {return next;} else {// Switch to next listlevel --;}}} 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/900744.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ROCm技术小结与回顾(下)

示例3–V_MFMA_F64_4x4x4F64 考虑V_MFMA_F64_4x4x4F64指令,它计算大小为44的四个独立矩阵块的MFMA。执行的操作是 ,其中 , , 和 都是大小为44元素的矩阵,N=0,1,2,3。下面的两张图显示了 1)输入参数A和B的四个分量的大小和形状,如图4-18所示。 2)分量映射到波阵面所拥有…

ROCm技术小结与回顾(上)

ROCm技术小结与回顾 在这一部分中,首先检查了Kernel 5在各种AMD GPU和问题大小上的性能,并注意到当网格超过一定大小阈值时,性能似乎会急剧下降。通过实验确定,LLC的大小是大型xy平面问题性能的限制因素。提出了两种不同的解决方法来规避缓存大小的问题,这两种方法都只需要…

有限差分法——拉普拉斯第4部分

有限差分法——拉普拉斯第4部分 提出了拉普拉斯算子有限差分法的HIP实现,并应用了四种不同的优化。在这些代码修改过程中,观察到由于全局内存的总取数减少,性能得到了逐步提高。然后,应用了进一步的优化,以在512512512上达到预期的性能目标MI250X GPU的单个GCD上的512个点…

推荐几本书1《AI芯片开发核心技术详解》、2《智能汽车传感器:原理设计应用》、3《TVM编译器原理与实践》、4《LLVM编译器原理与实践》,谢谢

4本书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该…

WebKit Inside: CSS 的匹配原理

WebKit Inside: CSS 的匹配原理相关文章WebKit Inside: CSS 样式表的解析 WebKit Inside: CSS 样式表的匹配时机 WebKit Inside: Acitvie 样式表 当WebView解析完所有外部与内联样式表,就要进入到CSS样式表的匹配阶段。 1 相关类图 WebKit中参与CSS样式表匹配的主要类如下图所…

助记词-公私钥-子私钥派生-钱包地址原理及实现

0x01.简介 现在各种DEX、钱包插件中的钱包导入及创建,大部分是通过助记词来备份的; 助记词是明文私钥的一种表现形式,最早由BIP39提出,为了帮助用户记住复杂的私钥; 一组助记词可以生成各个链上的公私钥,进而可以算出钱包地址;掌握了助记词,就代表掌握了该组助记词上的…

AI 代理的未来是事件驱动的

AI 代理即将彻底改变企业运营,它们具备自主解决问题的能力、适应性工作流以及可扩展性。但真正的挑战并不是构建更好的模型。 代理需要访问数据、工具,并且能够在不同系统之间共享信息,其输出还需要能被多个服务(包括其他代理)使用。这不是一个 AI 问题,而是一个基础设施…

树莓派 3B + Bookworm:mjpg-streamer 正确安装全流程(原创)

在树莓派 OS Bookworm 版本上安装 mjpg-streamer 并非像旧版本一样简单,许多网上的教程已经过时,甚至存在错误。我在尝试过程中遇到了多个问题,例如依赖库缺失、编译失败等,但最终成功解决并搭建了 远程视频流监控系统。本教程基于 树莓派 3B,整理了一套 完整、可复现 的 …

1.匀速圆周运动

1.平面中的匀速圆周运动 例子:一个物体在半径为r的圆形路径中以恒定大小的速度s移动。 建立一个二维坐标系,物体位于平面上,圆心在原点上。物体的瞬时速度v(t)总是与其运动轨迹相切,所以物体任意时刻的速度与轨迹圆相切,并且速度的大小:$|v(t)|=s$ 下图右侧的两个三角形,…

Fiddler如何抓取HTTPS请求

如果发现fiddler只能抓取http请求,但是抓取不到HTTPS请求,看查看是不是没有勾选解密https流量入口:Tools——>Options——>HTTPS,勾选以下选框设置完成过后可以正常抓取HTTPS的请求了

愿景2025|未来已来 各地未来产业加速布局

各地2025年政府工作报告显示,从东部沿海到中西部内陆,从人工智能到低空经济,从量子科技到生物制造,新兴产业和未来产业的布局正在加速展开,这些产业不仅成为各地抢占发展新赛道的重要抓手,更是推动经济高质量发展的新增长极。