多线程同步和加锁的方式
1. 互斥锁(Mutex)
互斥锁是一种常见的线程同步机制,用于保护共享资源,确保同一时间只有一个线程可以 访问该资源。C++标准库提供了std::mutex类来实现互斥锁。
std::mutex的lock()成员函数获取锁,使用完毕后调用unlock()释放锁。推荐使用std::lock_guard或std::unique_lock等封装类,他们可以在构造时自动加锁,在析构式自动解锁,从而简化代码并减少死锁风险。
#include <mutex>
#include <thread>
std::mutex mtx;
void threadFunction()
{
std::lock_guard<std::mutex> lock(mtx); // 自动加锁
// 临界区代码
}
int main()
{
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
return 0;
}
2. 递归锁
递归锁是互斥锁的一种特殊形式,允许同一线程多次获得锁而不会导致死锁,C++标准提供了std::recursive_mutex类来实现递归锁。支持同一现成多次调用lock()。
#include <mutex>
#include <thread>
std::recursive_mutex rmtx;
void recursiveFunction()
{
std::lock_guard<std::recursive_mutex> lock(rmtx); // 递归调用或再次加锁
}
int main()
{
// ...(与互斥锁示例相同)
}
3. 条件变量(Condition Variable)
条件变量用于线程间的等待和唤醒操作,通常与互斥锁一起使用,C++标准库提供了std::condition_variable和std::condition_variable_any类来实现条件变量。
使用方式:线程在等待某个条件成立时,会先加锁互斥锁,然后调用条件变量的wait()函数进入等待状态并释放锁。当条件成立时,另一个线程会调用notify_one()或notify_all()来唤醒一个或所有等待的线程。
#include <condition_variable>
#include <mutex>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id)
{
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck); // ... 当ready为true时,执行临界区代码
}
void go()
{
std::unique_lock<std::mutex> lck(mtx);
ready = true; cv.notify_all(); // 唤醒所有等待的线程
}
int main()
{
std::thread threads[10]; // 创建线程...
go();
// 设置ready为true并唤醒所有线程
// 等待线程结束...
}
4. 原子操作(Atomic Operation)
原子操作可以保证操作的不可分割性,即操作在执行过程中不会被其他线程打断。C++标准库提供了std::atomic模板类来实现原子操作。
使用方式:直接使用std::atomic模板类封装的变量进行操作,这些操作会自动地成为原子操作。
#include <atomic>
#include <thread>
std::atomic<int> count(0);
void increment()
{
++count; // 原子操作
}
int main()
{
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join(); // 此时count的值至少为2
}
5. 信号量(Semaphore)
信号量用于控制多个线程对共享资源的访问顺序和数量。C++20标准库引入了std::semaphore类来实现信号量。
使用方式:通过std::semaphore的acquire()和release()成员函数来控制资源的访问。
#include <semaphore>
#include <thread>
std::semaphore sem(2); // 允许两个线程同时访问
void task()
{
sem.acquire(); // 等待信号量
// 访问共享资源
sem.release(); // 释放信号量
}
int main()
{
std::thread threads[5]; // 创建并启动线程...
// 等待线程结束...
}
标签:std,多线程,lock,C++,互斥,加锁,线程,include
From: https://blog.csdn.net/qq_38556796/article/details/143183917