std::mutex用于保护共享数据,配合std::lock_guard或std::unique_lock实现线程安全;示例展示两个线程对计数器加锁递增,确保结果正确;std::lock_guard自动管理锁生命周期,防止死锁;std::unique_lock支持延迟加锁和手动控制,适用于复杂场景;使用std::lock和固定顺序获取多把锁可避免死锁;合理控制临界区大小以提升性能。

在C++多线程编程中,std::mutex 是最常用的同步工具之一,用于保护共享数据,防止多个线程同时访问造成数据竞争。它定义在 头文件中,配合 std::lock_guard 或 std::unique_lock 使用,能有效确保临界区的互斥访问。
基本用法:保护共享资源
当多个线程需要修改同一个变量时,必须使用互斥锁来串行化访问。例如,两个线程同时对一个全局计数器进行递增操作,若不加锁,可能导致结果错误。
示例代码:
#include #include #include int counter = 0;std::mutex mtx; // 定义互斥锁void increment() { for (int i = 0; i < 100000; ++i) { std::lock_guard lock(mtx); // 自动加锁/解锁 ++counter; }}int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Final counter value: " << counter << std::endl; return 0;}
在这个例子中,std::lock_guard 在构造时自动加锁,析构时自动释放锁,避免了忘记解锁导致的死锁问题。
立即学习“C++免费学习笔记(深入)”;
std::unique_lock 的灵活控制
相比 std::lock_guard,std::unique_lock 提供了更多灵活性,比如可以延迟加锁、手动控制加锁与解锁时机,甚至支持条件变量。
示例:手动控制锁的范围
std::mutex mtx;std::unique_lock lock(mtx, std::defer_lock); // 不立即加锁// ... 做一些不需要锁的操作lock.lock(); // 手动加锁// 访问共享资源++counter;lock.unlock(); // 可以提前释放锁
这种机制适合在临界区较短或需要在加锁前后执行其他操作的场景。
避免死锁的常见技巧
多个互斥锁同时使用时容易发生死锁。例如线程A持有锁1并等待锁2,而线程B持有锁2并等待锁1。
解决方法包括:
始终以相同的顺序获取多个锁使用 std::lock 一次性锁定多个互斥量,避免中间状态
示例:安全地锁定两个互斥量
std::mutex mtx1, mtx2;void thread_func() { std::lock(mtx1, mtx2); // 同时尝试获取两个锁 std::lock_guard lock1(mtx1, std::adopt_lock); std::lock_guard lock2(mtx2, std::adopt_lock); // 使用共享资源}
这里 std::adopt_lock 表示构造 lock_guard 时不重新加锁,而是接管已持有的锁。
基本上就这些。只要合理使用 std::mutex 配合 RAII 风格的锁管理,就能写出安全高效的并发程序。关键是把临界区控制得越小越好,避免长时间持锁影响性能。
以上就是C++怎么使用std::mutex进行线程同步_C++并发编程与互斥锁应用的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1486313.html
微信扫一扫
支付宝扫一扫