C++ 多线程(互斥锁、条件变量)

互斥锁

最简单示例:

cpp 复制代码
#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之间需要一个同步信号,来统一控制线程是否该运行或者等待

cpp 复制代码
#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;
}
相关推荐
ELI_He9992 分钟前
PHP中替换某个包或某个类
开发语言·php
小林熬夜学编程6 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
m0_748236119 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
倔强的石头10617 分钟前
【C++指南】类和对象(九):内部类
开发语言·c++
Watermelo61722 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导2 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Evand J2 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab
LucianaiB2 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python