C++ 多线程之互斥量(mutex)详解
什么是互斥量?
在C++中,当多个线程同时访问共享资源时,可能会发生数据冲突或数据竞争的问题,导致程序出错。互斥量就是一种保持互斥、防止数据冲突的机制。在使用互斥量时,只有获取了互斥量的线程才能访问被保护的共享资源,其他线程必须等待。当获取互斥量的线程访问结束并释放互斥量后,其他线程才能继续获取互斥量并访问共享资源。
互斥量的类型
在C++中,有几种互斥量的类型,可以根据需求进行选择:
std::mutex
: 最基本的互斥量类型,可以将临界区的代码封装到一个块中,并通过锁定互斥量保证同一时间只有一个线程可以进入该块。std::recursive_mutex
: 可递归的互斥量类型,允许同一个线程多次获取该互斥量而不会引起死锁。std::timed_mutex
: 有超时限制的互斥量类型,支持 lock_for() 和 lock_until() 函数,可以设置等待互斥量的时间。std::recursive_timed_mutex
: 具有递归和超时限制的互斥量类型。
std::mutex 示例
#include <iostream>
#include <thread>
#include <mutex>
int num = 0;
std::mutex mtx;
void increment() {
for(int i = 0; i < 10000; i++) {
mtx.lock();
num++;
mtx.unlock();
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << num << std::endl;
return 0;
}
上述示例代码中,我们定义了一个整型变量 num
,然后创建了两个线程 t1 和 t2,并且让它们同时访问 num
变量。为了避免数据冲突,我们使用了 std::mutex
保护临界区,即在对 num
变量操作时先获取互斥量,然后再释放互斥量。运行上述代码,输出的结果应该是 20000
,即两个线程共同对 num
进行了 20000 次加一操作。
std::recursive_mutex 示例
#include <iostream>
#include <mutex>
std::recursive_mutex rmutex;
void foo(int n) {
rmutex.lock();
if(n == 0) {
std::cout << "End" << std::endl;
}
else {
std::cout << n << std::endl;
foo(n - 1);
}
rmutex.unlock();
}
int main() {
foo(5);
return 0;
}
上述示例代码中,我们定义了递归函数 foo()
,它会从 5 依次打印每个数字,直到打印 0 即结束。在 foo()
函数中,我们使用了 std::recursive_mutex
保护递归调用的临界区。由于 foo()
函数是递归的,所以线程在递归调用时会多次获取并释放互斥量。然而,由于我们使用了 std::recursive_mutex
,所以这样的递归调用不会导致死锁。在运行上述代码时,我们可以看到程序正常结束,输出了从 5 到 0 的数字。
总结
以上就是 C++ 多线程之互斥量(mutex)的详解,其基本作用就是防止数据冲突和数据竞争问题。在使用互斥量时,可以选择不同类型的互斥量,以满足不同的需求。同时,为了避免出错,使用互斥量时要保证每次获取互斥量后都一定要释放。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 多线程之互斥量(mutex)详解 - Python技术站