Mutex 代表互斥。在 C++ 中,std::mutex 类是一个同步原语,用于保护共享数据不被多个线程同时访问。共享数据可以是变量、数据结构等形式。
std::mutex类在 C++ 中实现互斥锁。它在头文件中定义。
C++ 中需要互斥锁
在 C++ 中,当多个线程同时修改相同的共享资源时,可能会引起竞争条件。它可能会在执行程序时产生不可预测的输出或意外行为。互斥锁用于通过锁定当前线程来避免竞争条件,以便所有其他线程当时无法访问共享资源,并在当前线程完成时解锁它。
C++ 中 Mutex 的语法
互斥锁的使用可以分为三步:
1.创建一个 std::mutex 对象
std::mutex mutex_object_name;
- 锁定线程
std::mutex 类的lock ()函数锁定线程,并且只允许当前线程运行,直到解锁为止。它可以防止多个线程同时访问共享资源。 - 解锁线程
std::mutex 函数的unlock ()用于在执行包含可能发生竞争条件的代码段后释放锁。它恢复所有等待的线程。
mutex_object_name.unlock ()
C++ 中的互斥锁示例
让我们创建一个共享整数变量,该变量可以在程序内部全局访问。创建一个函数,使用 for 循环将数字增加 1000000 次。创建两个名为 thread1 和 thread2 的线程来运行相同的increment() 函数。
在这种情况下,线程 1 将把数字加 1,执行 1000000 次,线程 2 将把数字加 1,执行 1000000 次。因此预期输出为 2000000。
然而,当多个线程试图同时修改同一资源时,可能会出现竞争条件。因此无法预测该数字的值
不使用互斥锁同步的代码
// C++ program to illustrate the race conditions
#include <iostream>
#include <thread>
using namespace std;
// Shared resource
int number = 0;
// function to increment the number
void increment(){
// increment number by 1 for 1000000 times
for(int i=0; i<1000000; i++){
number++;
}
}
int main()
{
// Create thread t1 to perform increment()
thread t1(increment);
// Create thread t2 to perform increment()
thread t2(increment);
// Start both threads simultaneously
t1.join();
t2.join();
// Print the number after the execution of both threads
cout << "Number after execution of t1 and t2 is " << number;
return 0;
}
输出
执行同一程序三次,观察在没有线程同步的情况下修改共享资源时的行为。
Number after execution of t1 and t2 is 15923263lg@lg-vm:~/lg/c++/18$ ./a.out
Number after execution of t1 and t2 is 13843590lg@lg-vm:~/lg/c++/18$ ./a.out
Number after execution of t1 and t2 is 16377696lg@lg-vm:~/lg/c++/18$ ./a.out
解释 很明显,程序的输出是不可预测的。当两个线程同时运行时,会导致竞争情况,从而产生不可预测的输出。不能保证输出为 2000000。这种不可预测的行为是由于使用多个线程同时修改同一个共享变量而发生的。
具有互斥同步的代码
// C++ program to illustrate the thread synchronization using mutex
#include <iostream>
#include <thread>
using namespace std;
// import mutex from C++ standard library
#include <mutex>
// Create object for mutex
mutex mtx;
// Shared resource
int number = 0;
// function to increment the number
void increment(){
// Lock the thread using lock
mtx.lock();
// increment number by 1 for 1000000 times
for(int i=0; i<1000000; i++){
number++;
}
// Release the lock using unlock()
mtx.unlock();
}
int main()
{
// Create thread t1 to perform increment()
thread t1(increment);
// Create thread t2 to perform increment()
thread t2(increment);
// Start both threads simultaneously
t1.join();
t2.join();
// Print the number after the execution of both threads
std::cout<<"Number after execution of t1 and t2 is "<<number;
return 0;
}