c++多线程(互斥量、原子变量、条件变量、信号量、promise、future)

c++多线程

一:创建线程(thread)

https://blog.csdn.net/qq_46470984/article/details/125334459?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167619985416800182782048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167619985416800182782048&biz_id=0&spm=1018.2226.3001.4450

ps:线程thread类不能直接返回函数的返回值,所以会在函数的参数中增加一个参数来保存结果。
二: 互斥量(mutex), 原子变量(atomic)
当多个线程同时对同一数据进行操作时造成线程不安全,无法得到预期的结果。所以要对数据进行保护。简单理解就是:在调用数据之前对数据进行上锁,使用完数据后再对数据进行解锁。这样当数据被使用时,由于数据提前被上锁则其他线程无法访问,避免了多个线程同时处理数据产生的问题。

https://blog.csdn.net/qq_46470984/article/details/125334818?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167619985416800182782048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167619985416800182782048&biz_id=0&spm=1018.2226.3001.4450

lock_gard和unique_lock只在离开作用域时解锁,在下面代码中将一直执行到for循环结束。
unique_lock可以通过lock.unlock()设置解锁位置。

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>

std::mutex mtx;
int globalVariable = 0;
//std::atomic<int> globalVariable = 0;

void task1()
{
    for (int i = 0; i < 1000; i++)
    {
        std::lock_guard<std::mutex> lock(mtx);
        //mtx.lock();
        globalVariable++;
        //mtx.unlock();

        std::cout << "task1: globalVariable is " << globalVariable << std::endl;
    }
}

void task2()
{
    for (int i = 0; i < 1000; i++)
    {
        std::unique_lock<std::mutex> lock(mtx);
        globalVariable--;
        //unique_lock可以通过lock.unlock()设置解锁位置
        lock.unlock();

        std::cout << "task2: globalVariable is " << globalVariable << std::endl;
    }
}

int main()
{
    std::thread t1(task1);
    std::thread t2(task2);

    t1.join();
    t2.join();

    std::cout << "current value is " << globalVariable;
}

在图片描述三:C++ 多线程并发 基础入门教程 1.3 条件变量(condition_variable), 信号量(semaphore)
1.条件变量(condition_variable)

https://blog.csdn.net/qq_46470984/article/details/125340274?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167619985416800182782048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167619985416800182782048&biz_id=0&spm=1018.2226.3001.4450

1)引出问题:while循环很占CPU
使用std::this_thread::sleep_for会缓解循环,但是延迟的时间不好设定,影响程序运行。使用条件变量(condition_variable)可以使程序平时处于休眠(wait)的状态,在满足某一条件时再被唤醒(notify)开始运行,避免资源的占用。
2)使用条件变量(condition_variable)引入两个消费者线程同时对生产者线程操作时,可能会出现虚假唤醒。即当某个条件并没有被实际满足时,线程依旧被唤醒。
例子:消费者一被唤醒,从队列中将数据取出;这时生产者又将新的数据压入队列,新唤醒消费者二线程;新的数据被之前的消费者一线程先推出队列,这时消费者二就找不到数据,导致虚假唤醒。
解决办法:可以使用while循环来判断队列是否为空,对队列一直进行监控,这也可以解决虚假唤醒。
2.信号量(semaphore)
不同于mutex可以允许同一个资源被多个线程访问。
调用acquire时使得信号量semaphore自身的计数器减一,变为负数后acquire阻塞。直到调用release时使计数器增加。
binary_semaphore 条件信号量计数器只有0、1两个值,release默认为1,也只能为1。它是counting_semaphore 计数信号量的特殊情况,相当于:std::binary_semaphore = std::counting_semaphore<1>

四:C++ 多线程并发 基础入门教程 1.4 promise future

https://blog.csdn.net/qq_46470984/article/details/125343241?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167619985416800182782048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167619985416800182782048&biz_id=0&spm=1018.2226.3001.4450

promise和future为模板类,promise提前承诺会在未来传递给future一个数值,future接收到数值后再传递给程序。
一、常规操作的大致流程如下:线程承诺给主函数一个数值
1)首先声明模板类promise对象p,然后再声明模板类future对象f。promise和future通过p.get_future()联系在一起。
2)通过引用p传递给未来产生数据的线程,一般也就是线程的输出。3)通过set_value函数获得承诺给future的数据。
4)f通过get函数读取到p传递过来的数据。get函数会使程序一直阻塞,直到promise完成set_value的操作。
二、反向操作:主线程承诺给线程一个数值。
1)同一
2)通过引用将f传递给未来接收数据的线程,一般也就是线程的输入
3)在后面的主程序中获得传递给线程的数值后,通过set_value函数获得承诺给future的数据。
4)子线程中,f通过get函数读取到p传递过来的数据。get函数会使程序一直阻塞,直到promise完成set_value的操作。
五:C++ 多线程并发 基础入门教程 1.5 std::packaged_task std::async

https://blog.csdn.net/qq_46470984/article/details/125343947?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167619985416800182782048%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167619985416800182782048&biz_id=0&spm=1018.2226.3001.4450

视频地址:https://space.bilibili.com/25594943/channel/seriesdetail?sid=2520972

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
互斥条件变量C++ 中常用的同步机制,用于在多线程编程中控制共享资源的访问和线程间的通信。 互斥(Mutex)用于保护共享资源,在访问共享资源之前需要获得互斥锁,访问完毕后需要释放互斥锁。具体使用方法如下: ```c++ #include <mutex> std::mutex mtx; // 定义互斥锁 // 在访问共享资源之前加锁 mtx.lock(); // 访问共享资源 // 在访问共享资源之后释放锁 mtx.unlock(); ``` 条件变量(Condition variable)用于线程间的通信,一个线程可以通知另一个线程一些特定的事件已经发生。具体使用方法如下: ```c++ #include <condition_variable> #include <mutex> std::condition_variable cv; // 定义条件变量 std::mutex mtx; // 定义互斥锁 bool flag = false; // 条件变量依赖的标志变量 // 线程 1 std::unique_lock<std::mutex> lck(mtx); // 获得互斥锁 while(!flag) cv.wait(lck); // 等待条件变量 // 执行线程 1 的任务 // 线程 2 { std::lock_guard<std::mutex> guard(mtx); // 获得互斥锁 // 执行线程 2 的任务 flag = true; } cv.notify_one(); // 通知条件变量 ``` 在上述代码中,线程 1 获得互斥锁后,检查标志变量 `flag` 是否满足条件,如果不满足,则进入等待状态,并释放互斥锁;线程 2 在获得互斥锁后,设置标志变量 `flag` 为真,并通知条件变量 `cv`,线程 1 得到通知后重新检查标志变量,如果满足条件,则执行线程 1 的任务。 需要注意的是,在使用条件变量时,必须获得互斥锁,以避免竞态条件的发生。另外,条件变量的使用通常需要和互斥锁一起使用,以确保线程安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值