递归使用场景

阐述了递归在文件夹树、CIT结构及组织架构层级中的应用,详细解释了如何通过递归查找特定属性及其重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

凡是类似于【树】的结构都能适用于递归。
例如: 文件夹树, CIT带有parent的数据结构。
某个CIT他的属性继承与其父亲,所以要查找某个CIT的属性,需要递归的把其所有的上层接点的属性全部拿出来。

组织架构的层级关系。
递归锁(`std::recursive_mutex` 或 `std::recursive_timed_mutex`)是 C++ 中允许**同一线程多次加锁**的互斥量,解决了普通互斥量(如 `std::mutex`)因重复加锁导致的死锁问题。其核心特性是**线程可重复获取已持有的锁**,适用于需要**嵌套调用**或**递归函数**中保护共享资源的场景。以下是详细说明: --- ### **1. 递归锁的核心特性** - **同一线程可重复加锁**: - 若线程已持有锁,再次调用 `lock()` 会成功(计数器+1),而非阻塞。 - 需对应次数的 `unlock()` 才能完全释放锁(计数器归零)。 - **其他线程阻塞**: - 其他线程尝试获取锁时,仍会阻塞,直到锁被完全释放。 - **避免自死锁**: - 普通互斥量在递归或嵌套调用中可能导致死锁(如线程A持有锁时再次尝试获取同一锁)。 - 递归锁通过计数器机制避免此问题。 --- ### **2. 典型使用场景** #### **(1) 递归函数中保护共享资源** 当递归函数需要访问共享数据时,普通互斥量会导致死锁,而递归锁可安全处理。 **示例:递归计算阶乘并保护共享变量** ```cpp #include <iostream> #include <mutex> #include <thread> std::recursive_mutex rmtx; int shared_count = 0; int factorial(int n) { std::lock_guard<std::recursive_mutex> lock(rmtx); // 可重复加锁 shared_count++; // 修改共享数据 if (n <= 1) return 1; return n * factorial(n - 1); // 递归调用 } int main() { std::thread t1(factorial, 5); std::thread t2(factorial, 3); t1.join(); t2.join(); std::cout << "Shared count: " << shared_count << std::endl; return 0; } ``` **关键点**: - `factorial()` 递归调用时,同一线程多次获取 `rmtx` 不会阻塞。 - 若使用 `std::mutex`,第二次 `lock()` 会导致死锁。 --- #### **(2) 嵌套函数调用中保护共享资源** 当函数A调用函数B,且两者均需访问共享数据时,递归锁可避免死锁。 **示例:嵌套调用中的日志记录** ```cpp #include <iostream> #include <mutex> #include <string> std::recursive_mutex log_mutex; void log(const std::string& msg) { std::lock_guard<std::recursive_mutex> lock(log_mutex); std::cout << msg << std::endl; } void process_data() { std::lock_guard<std::recursive_mutex> lock(log_mutex); log("Processing data..."); // 嵌套调用 // 修改共享数据... } int main() { process_data(); return 0; } ``` **关键点**: - `process_data()` 和 `log()` 均需获取 `log_mutex`,递归锁允许嵌套获取。 --- #### **(3) 复杂对象的方法调用链** 当对象的多个方法需访问内部共享状态,且方法间可能相互调用时,递归锁可简化设计。 **示例:银行账户类的安全操作** ```cpp #include <iostream> #include <mutex> class BankAccount { std::recursive_mutex mtx; double balance; public: BankAccount(double init) : balance(init) {} void deposit(double amount) { std::lock_guard<std::recursive_mutex> lock(mtx); balance += amount; log("Deposit completed"); } void withdraw(double amount) { std::lock_guard<std::recursive_mutex> lock(mtx); if (balance >= amount) { balance -= amount; log("Withdrawal completed"); } else { log("Insufficient funds"); } } void log(const std::string& msg) { std::lock_guard<std::recursive_mutex> lock(mtx); // 嵌套调用 std::cout << "Account log: " << msg << ", Balance: " << balance << std::endl; } }; int main() { BankAccount acc(1000); acc.deposit(500); acc.withdraw(200); return 0; } ``` **关键点**: - `deposit()`、`withdraw()` 和 `log()` 均需保护 `balance`,递归锁允许方法间安全调用。 --- ### **3. 递归锁 vs 普通互斥量** | 特性 | `std::recursive_mutex` | `std::mutex` | |---------------------|----------------------------------|----------------------------------| | 同一线程重复加锁 | 允许(计数器+1) | 阻塞(导致死锁) | | 性能 | 略低(需维护计数器) | 更高 | | 适用场景 | 递归/嵌套调用、复杂对象方法链 | 简单同步、无嵌套的临界区 | | 设计复杂度 | 较高(需注意加锁/解锁次数) | 较低 | --- ### **4. 注意事项** #### **(1) 避免过度使用** - 递归锁可能掩盖设计问题(如函数职责不清晰)。 - 优先通过重构代码(如拆分函数、减少嵌套)避免递归锁需求。 #### **(2) 确保解锁次数匹配** - 每次 `lock()` 必须对应一次 `unlock()`,否则锁无法被其他线程获取。 - 推荐使用 `std::lock_guard` 或 `std::unique_lock` 自动管理锁生命周期。 #### **(3) 死锁风险仍存在** - 递归锁仅解决**同一线程重复加锁**的死锁,不同线程间的死锁仍需通过锁顺序、条件变量等机制避免。 **示例:不同线程间的死锁(递归锁无法解决)** ```cpp std::recursive_mutex mtx1, mtx2; void thread1() { std::lock_guard<std::recursive_mutex> lock1(mtx1); std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::lock_guard<std::recursive_mutex> lock2(mtx2); // 可能阻塞 } void thread2() { std::lock_guard<std::recursive_mutex> lock2(mtx2); std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::lock_guard<std::recursive_mutex> lock1(mtx1); // 可能阻塞 } ``` **解决**:通过固定锁的获取顺序(如先 `mtx1` 后 `mtx2`)避免死锁。 --- ### **5. 递归锁的变种:`std::recursive_timed_mutex`** - 支持超时加锁(`try_lock_for()`/`try_lock_until()`),适用于需要避免长时间阻塞的场景。 - **示例**: ```cpp std::recursive_timed_mutex rtmx; if (rtmx.try_lock_for(std::chrono::milliseconds(100))) { // 获取锁成功 rtmx.unlock(); } else { // 超时未获取锁 } ``` --- ### **6. 总结** - **递归锁适用场景**: 1. 递归函数中保护共享资源。 2. 嵌套函数调用中保护共享资源。 3. 复杂对象的方法调用链(如银行账户类)。 - **核心优势**:避免同一线程因重复加锁导致的死锁。 - **设计建议**:优先通过重构减少嵌套,仅在必要时使用递归锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值