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

C++11中的同步互斥机制详解

文章目录

      • 互斥锁:std::mutex
        • 什么是 `std::mutex`
        • `std::mutex` 的使用
        • 存在的问题
      • std::lock_guard:自动管理锁的RAII机制
        • 什么是 `std::lock_guard`
        • 使用 `std::lock_guard`
      • std::unique_lock:更灵活的锁管理
        • 什么是 `std::unique_lock`
        • `std::unique_lock` 的使用
      • 条件变量:std::condition_variable
        • 什么是 `std::condition_variable`
        • 条件变量的使用
        • `wait` 的工作原理
      • 其他C++11同步机制

在并发编程中,多个线程共享资源时,互斥同步是避免数据竞争和保证数据一致性的关键手段。C++11引入了一系列强大的线程和同步库,包括互斥(mutex)和条件变量(condition_variable

本篇博客将详细介绍 C++11 中的互斥同步机制,重点包括 std::mutexstd::lock_guardstd::unique_lock 以及条件变量的使用场景和实现原理。


互斥锁:std::mutex

什么是 std::mutex

std::mutex 是 C++11 提供的最基本的互斥锁,用于保护共享资源,确保同一时刻只有一个线程能够访问该资源。它提供了 lock()unlock() 两个基本方法,分别用于加锁和解锁。

std::mutex 的使用
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx; // 全局互斥锁
int counter = 0; // 全局共享资源void increment() {mtx.lock(); // 加锁++counter;  // 修改共享资源mtx.unlock(); // 解锁
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final counter: " << counter << std::endl;return 0;
}

在这个例子中,两个线程 t1t2 都在对 counter 进行自增操作。通过 std::mutex 进行加锁和解锁,确保了同一时刻只有一个线程能够访问和修改 counter,避免了数据竞争。

存在的问题

虽然 std::mutex 提供了基础的互斥功能,但手动调用 lock()unlock() 容易出错。例如,如果程序在 lock() 后发生异常或者忘记调用 unlock(),就可能导致死锁或资源长时间被占用。因此,C++11 提供了 std::lock_guardstd::unique_lock 来简化锁的管理。


std::lock_guard:自动管理锁的RAII机制

什么是 std::lock_guard

std::lock_guard 是 C++11 提供的 RAII(资源获取即初始化)机制的封装类,用于自动管理 mutex 的生命周期。构造时加锁,析构时解锁,确保在函数作用域结束时自动释放锁,避免了手动管理锁的复杂性。

使用 std::lock_guard
void increment() {std::lock_guard<std::mutex> guard(mtx); // 自动加锁++counter;  // 修改共享资源
}  // 离开作用域时自动解锁

在上面的代码中,当 guard 对象离开作用域时,mutex 会被自动解锁,即使发生异常也不会忘记解锁,从而大大提升了代码的健壮性。


std::unique_lock:更灵活的锁管理

什么是 std::unique_lock

std::unique_lock 是一个比 std::lock_guard 更加灵活的锁管理类。与 std::lock_guard 不同,std::unique_lock 支持:

  • 延迟锁定:可以在对象创建时不锁定,而在需要时调用 lock()
  • 提前解锁:可以手动调用 unlock() 解除锁定。
  • 通过 try_lock() 尝试加锁,而不是等待锁定。
std::unique_lock 的使用
void increment() {std::unique_lock<std::mutex> ulock(mtx); // 加锁++counter;ulock.unlock(); // 提前解锁// 其他非共享资源的操作
}

std::unique_lock 提供了更灵活的加锁和解锁控制,非常适合需要手动解锁或多次锁定的场景。尽管灵活性增加,但一般情况下仍推荐使用简单的 std::lock_guard,除非确实需要这种额外的灵活性。


条件变量:std::condition_variable

什么是 std::condition_variable

std::condition_variable 是一个同步机制,用于让一个线程等待另一个线程满足某个条件。条件变量通常与 std::unique_lock 一起使用,因为它要求有灵活的锁定和解锁操作。

条件变量的使用
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; }); // 等待条件满足std::cout << "Thread is running" << std::endl;
}void signal() {std::this_thread::sleep_for(std::chrono::seconds(1));{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one(); // 通知一个等待线程
}int main() {std::thread t1(worker);std::thread t2(signal);t1.join();t2.join();return 0;
}

在这个例子中,worker 线程在等待条件变量 cv,直到 ready 变为 truesignal 线程在修改 ready 后,通过 notify_one() 唤醒等待的线程。

wait 的工作原理

wait() 方法会先解锁传入的互斥锁,然后进入阻塞状态。当条件满足时,它会重新加锁并继续执行。条件变量常用于生产者-消费者模型或多线程任务调度。


其他C++11同步机制

除了 std::mutex 及其相关工具,C++11 还提供了其他几种常用的同步机制:

  • std::recursive_mutex:允许同一线程多次加锁,而不会导致死锁。
  • std::timed_mutex:支持超时的 mutex,可以使用 try_lock_fortry_lock_until 进行定时加锁。
  • std::shared_mutex:允许多个线程共享读锁定,适用于读多写少的场景。

http://www.mrgr.cn/news/58923.html

相关文章:

  • 【日常记录-Java】可变长度参数
  • SQLI LABS | Less-10 GET-Blind-Time based-double quotes
  • Flutter不常用组件----InteractiveViewer
  • 学习笔记——路由——IP组播-PIM-DM(密集模式)前言概述
  • HTML 与 CSS 演绎敲击键盘的灵动之手
  • 【VUE点击父组件按钮,跳转到子组件】
  • 04 P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
  • P1781 宇宙总统
  • MYSQL-查看创建的用户语法(十一)
  • 代码随想录算法训练营第二十七天 | 122.买卖股票的最佳时机Ⅱ 55.跳跃游戏 45.跳跃游戏Ⅱ 1005.K次取反后最大化的数组和
  • Web环境下的Spring Boot酒店房间预订系统
  • [答疑]是不是互联网更适合用DDD
  • 从零开始:构建一个高效的开源管理系统——使用 React 和 Ruoyi-Vue-Plus 的实战指南
  • Spring Boot驱动的Web版酒店客房管理系统
  • 项目需要,写了一个取出8位变量的2bit数据,引发了思考!
  • 「漏洞复现」JEPaaS 低代码平台 j_spring_security_check SQL注入漏洞
  • Element 的Table表格实现列合并(记得先排序、element-plus、列合并、线上已投入使用)
  • 信息安全工程师(72)网络安全风险评估概述
  • Java Web 开发:构建动态与交互式Web应用的基石
  • R语言机器学习算法实战系列(十四): CatBoost分类算法+SHAP值 (categorical data gradient boosting)
  • vscode配色主题与图标库推荐
  • 本地缓存库分析(一):golang-lru
  • 厨艺交流平台:Spring Boot技术实践案例
  • 最佳B站视频下载工具 完全免费+支持8k画质!
  • Hadoop:yarn的Rust API接口
  • Nodejs使用pkg打包为可执行文件