互斥锁
最简单示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
int counter = 0;
void increment() {
for (int i = 0; i < 10000; ++i) {
// b1 是创建出来的对象. lock_guard 类似智能指针一样,为了防止忘记释放锁
// 锁的管理范围看作用域范围 {}
std::lock_guard<std::mutex> b1(mtx);
counter++;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Counter value: " << counter << std::endl;
return 0;
}
条件变量+互斥锁
互斥锁:保证只要一个线程在修改变量
条件变量:线程1与线程2之间需要一个同步信号,来统一控制线程是否该运行或者等待
#include <iostream>
#include <string>
#include <thread> // 多线程
#include <vector>
#include <mutex> // 互斥锁
#include <condition_variable> // 条件变量
#include <chrono> // 处理时间库
//using namespace std;
std::mutex mtx1; // 互斥锁对象
std::condition_variable cv_1; // 条件变量对象
bool state = false; // 条件变量 变量
// 不使用传递引用
//void read_camera(std::string rtsp, std::string window_name) {
// 使用传递引用避免拷贝
void read_camera(const std::string& rtsp, const std::string& window_name) {
// 互斥锁 使用
std::unique_lock<std::mutex> lck(mtx1);
while (!state) {
cv_1.wait(lck); // 条件不成立 进入阻塞状态 释放掉锁 等待别人唤醒
}
for (int i = 0; i < 9999; i++) {
std::cout << i << std::endl;
}
std::cout << "后启动的线程id:" << std::this_thread::get_id() << std::endl;
std::cout << "rtsp" << rtsp << std::endl;
std::cout << "window_name " << window_name << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2)); // 休眠2秒
}
void read_camera_1() {
std::cout << "线程id:" << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2)); // 休眠2秒
// 互斥锁 使用
std::unique_lock<std::mutex> lck(mtx1);
state = true;
cv_1.notify_all(); // 通知所有线程
}
int main()
{
单个线程启动
//std::string param1 = "./jian_qian.mp4";
//std::string param2 = "1";
//std::thread t1([param1, param2]() {
// read_camera(param1, param2);
// });
// 测试互斥锁 休眠2秒
std::thread t([ ]() {
read_camera_1();
});
// 循环启动线程
// 要保证容器内的数量一致
std::vector <std::string> camera_path{ "./jian_qian.mp4", "./jian_qian.mp4" };
std::vector <std::string> camera_name{ "1", "2" };
// 这里我用循环启动了2个线程,实际执行时,先会执行休眠2秒的函数,然后这两个线程会抢占运行先后顺序,
// 假如第一个抢到了,第二个要等第一个运行完毕后才能运行,因为代码中互斥锁+条件变量 是只有一个线程可以运行,其他需要等待。
std::vector<std::thread> threads;
for (int i = 0; i < camera_path.size(); i++) {
// 不传递引用
//threads.push_back(std::thread([camera_path_i = camera_path[i], camera_name_i = camera_name[i]]() {
// read_camera(camera_path_i, camera_name_i);
// }));
// 使用 std::ref 传递引用,避免值拷贝
threads.push_back(std::thread(read_camera, std::ref(camera_path[i]), std::ref(camera_name[i])));
}
t.join();
// 阻塞等待所有线程完成
for (auto& t : threads) {
// 避免重复启动线程,防止线程意外,未正确释放资源
if (t.joinable()) {
t.join();
}
}
return 0;
}