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

在C++多线程编程中,std::mutex 是最常用的同步工具之一,用于保护共享数据,防止多个线程同时访问造成数据竞争。它定义在 <mutex> 头文件中,配合 std::lock_guard 或 std::unique_lock 使用,能有效确保临界区的互斥访问。
当多个线程需要修改同一个变量时,必须使用互斥锁来串行化访问。例如,两个线程同时对一个全局计数器进行递增操作,若不加锁,可能导致结果错误。
示例代码:
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx; // 定义互斥锁
void increment() {
for (int i = 0; i < 100000; ++i) {
std::lock_guard<std::mutex> 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::lock_guard,std::unique_lock 提供了更多灵活性,比如可以延迟加锁、手动控制加锁与解锁时机,甚至支持条件变量。
示例:手动控制锁的范围
std::mutex mtx; std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // 不立即加锁 // ... 做一些不需要锁的操作 lock.lock(); // 手动加锁 // 访问共享资源 ++counter; lock.unlock(); // 可以提前释放锁
这种机制适合在临界区较短或需要在加锁前后执行其他操作的场景。
多个互斥锁同时使用时容易发生死锁。例如线程A持有锁1并等待锁2,而线程B持有锁2并等待锁1。
解决方法包括:
示例:安全地锁定两个互斥量
std::mutex mtx1, mtx2;
void thread_func() {
std::lock(mtx1, mtx2); // 同时尝试获取两个锁
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
// 使用共享资源
}这里 std::adopt_lock 表示构造 lock_guard 时不重新加锁,而是接管已持有的锁。
基本上就这些。只要合理使用 std::mutex 配合 RAII 风格的锁管理,就能写出安全高效的并发程序。关键是把临界区控制得越小越好,避免长时间持锁影响性能。
以上就是C++怎么使用std::mutex进行线程同步_C++并发编程与互斥锁应用的详细内容,更多请关注php中文网其它相关文章!
编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号