当前位置: 首页 > ai >正文

红黑树的线程安全的做法

🧭 本节概要

  1. 为什么红黑树需要线程安全
  2. 多线程下的读写冲突问题分析
  3. 常见加锁策略:粗粒度、细粒度、读写锁
  4. 使用 std::shared_mutex 实现线程安全的红黑树
  5. 读写并发模拟与完整 C++ 示例
  6. 总结和工程建议

一、为什么红黑树要线程安全?

红黑树本身是一种 高效平衡的搜索树,在内存管理、进程调度、数据库等系统中都有使用。在多线程环境中,多个线程同时访问/修改红黑树结构就可能出现如下问题:

❗常见冲突:
  • 线程 A 正在插入新节点,线程 B 同时查找或删除,会导致野指针访问
  • 线程 A 删除节点后旋转结构,线程 B 引用该节点时程序崩溃
  • 内存泄漏、死锁、脏读、写入丢失等

因此,确保红黑树线程安全至关重要


二、线程安全的几种策略

✅ 粗粒度锁(简单但影响并发)
  • 使用一个 mutex,所有操作(读写)都锁整个树
  • 优点:实现简单
  • 缺点:性能差,不支持读写并发
✅ 细粒度锁(复杂但高性能)
  • 每个节点加锁
  • 插入/删除时只锁路径上的节点
  • 实现复杂,要处理死锁问题
✅ 读写锁(推荐策略)
  • 使用 C++17 std::shared_mutex
  • 读操作加共享锁 shared_lock
  • 写操作加独占锁 unique_lock
  • 允许多个读线程并发读,写线程独占写

三、线程安全红黑树整体架构

template<typename Key, typename Value>
class ThreadSafeRBTree {
private:
struct Node {
Key key;
Value value;
Color color;
Node *left, *right, *parent;
Node(Key k, Value v): key(k), value(v), color(RED),
left(nullptr), right(nullptr), parent(nullptr) {}
};Node* root;
mutable std::shared_mutex tree_mutex; // 支持读写并发// 各种操作:插入、删除、查找等内部封装public:
ThreadSafeRBTree(): root(nullptr) {}void insert(Key key, Value value);
void erase(Key key);
bool find(Key key, Value& value);
};

四、核心操作:线程安全实现

✅ 插入(写操作:独占锁)
void insert(Key key, Value value) {std::unique_lock<std::shared_mutex> lock(tree_mutex);// 调用普通红黑树插入算法(略)...
}
✅ 查找(读操作:共享锁)
bool find(Key key, Value& value) {std::shared_lock<std::shared_mutex> lock(tree_mutex);Node* curr = root;while (curr) {if (key == curr->key) {value = curr->value;return true;} else if (key < curr->key)curr = curr->left;elsecurr = curr->right;}return false;
}
✅ 删除(写操作:独占锁)
void erase(Key key) {std::unique_lock<std::shared_mutex> lock(tree_mutex);// 调用红黑树删除算法(略)...
}

五、完整并发测试用例(含多线程插入 + 查找)

#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>
using namespace std;int main() {ThreadSafeRBTree<int, string> tree;// 插入线程thread t1([&tree]() {for (int i = 0; i < 100; ++i) {tree.insert(i, "value" + to_string(i));}});// 查找线程thread t2([&tree]() {for (int i = 0; i < 100; ++i) {string val;if (tree.find(i, val))cout << "Found " << i << ": " << val << endl;elsecout << "Not found: " << i << endl;}});t1.join();t2.join();
}

六、实战工程建议

场景

加锁策略

说明

单线程

无需锁

最快

多线程读 + 少量写

shared_mutex

性能好

写操作频繁

粗锁或细粒度锁

细粒度更高效但复杂

极致并发场景

无锁数据结构

使用 skiplist 或 lock-free tree


七、总结

  • 红黑树在并发场景下必须加锁
  • 推荐使用 C++17 提供的 shared_mutex 实现读写分离
  • 如果需要极致性能,需要进一步研究无锁算法(例如 epoch-based reclamation)
http://www.xdnf.cn/news/5405.html

相关文章:

  • 黑名单中的随机数-leetcode710
  • sunset:Solstice靶场
  • 动态规划之背包问题总结(Java)
  • 微服务架构-限流、熔断:Alibaba Sentinel入门
  • TIME - MoE 模型代码 4——Time-MoE-main/run_eval.py
  • 前端密码加密:保护用户数据的第一道防线
  • 《微服务设计》笔记
  • CSS:盒子阴影与渐变完全解析:从基础语法到创意应用
  • MySQL数据库容灾设计案例与SQL实现
  • 数据库的脱敏策略
  • 深入浅出之STL源码分析6_模版编译问题
  • 【Tools】git使用详解以及遇到问题汇总
  • 传感器:从单一感知到智能决策的跨越
  • Java基础(异常2)
  • MCP:重塑AI交互的通用协议,成为智能应用的基础设施
  • 【js基础笔记] - 包含es6 类的使用
  • C++(9):位运算符进阶版
  • 变换炉设备设计:结构优化与工艺集成
  • 使用vue3-seamless-scroll实现列表自动滚动播放
  • 中空电机在安装垂直轴高速电机后无法动平衡的原因及解决方案
  • 26考研——中央处理器_指令流水线_流水线的冒险与处理 流水线的性能指标 高级流水线技术(5)
  • LintCode第4题-丑数 II
  • java笔记06
  • Three.js + React 实战系列 - 联系方式提交表单区域 Contact 组件✨(表单绑定 + 表单验证)
  • 频率学派和贝叶斯学派置信区间/可信区间的区别
  • spark算子介绍
  • 机器视觉开发教程——C#如何封装海康工业相机SDK调用OpenCV/YOLO/VisionPro/Halcon算法
  • 高精地图数据错误的侵权责任认定与应对之道
  • 【PVE】ProxmoxVE8虚拟机,存储管理(host磁盘扩容,qcow2/vmdk导入vm,vm磁盘导出与迁移等)
  • 数据库分库分表实战指南:从原理到落地