c++11多线程同步与通信实践

  1. 任务目标
    (1)创建3个线程;
    (2)线程1不断的生成数值数据,模拟不断读取硬件设备数据,并打印原始数据;
    (3)线程2获取线程1的数据,对其进行处理1(乘以2),并打印中间结果;
    (4)线程3获取线程2的处理结果,进行处理2(乘以-1),并打印最终结果;
    (5)一组处理1和处理2结束后,线程2再接着获取线程1的数据,不断处理.

  2. 几点注意的地方
    (1)c++多线程用pthread还是thread
    网上对thread类评价很低,但是thread用起来简单,所以这里我用thread类.

(2)线程中输出函数
printf是线程安全的,用cout在线程中输出打印内容会经常错位,因此线程中最好用printf输出.

(3)线程结束的方法
join:主线程等待子线程结束后再结束;
detach:程序将子线程看成单独的线程,子线程会在后台运行.
我们一般用join().

(4)c++类与多线程封装
要想把创建和启动线程的函数放在类中,需要静态类成员的线程函数,但是静态成员函数又无法调用非静态成员变量和方法,虽然可以七拐八拐用上,但是实现过程太繁琐,得不偿失.因此这里我只讲线程函数和锁及过程数据变量封装在类中,创建线程和启动线程放在main()函数中.

3. 文件与代码
threadclass.hpp // 线程类的定义
threadclass.cpp // 线程类的实现
main.cpp // 创建和启动线程

(1) threadclass.hpp

#ifndef THREADCLASS_THREADCLASS_HPP
#define THREADCLASS_THREADCLASS_HPP
#include <mutex>
#include <condition_variable>
using namespace std;
class ThreadClass
{
private:
    int rawdata;
    int data;
    bool start;
    bool readyfor_t2;

    mutex mtx;
    condition_variable cv;

public:
    ThreadClass();
    ThreadClass(const int x, const int y, const bool s1, const bool s2);
    ~ThreadClass();
    void thread1(); // 生成数值并打印
    void thread2(); // 数值*2并打印
    void thread3(); // 在*2基础上数值*-1并打印
};

#endif //THREADCLASS_THREADCLASS_HPP

(2) threadclass.cpp

//条件变量和互斥锁实现线程同步和通信
// Created by wz on 2020/6/1.
#include "threadclass.hpp"
#include <thread>
#include <condition_variable>
using namespace std;

ThreadClass::ThreadClass()
{}

ThreadClass::~ThreadClass()
{}

ThreadClass::ThreadClass(const int x, const int y, const bool s1, const bool s2)
{
    rawdata = x;
    data = y;
    start = s1;
    readyfor_t2 = s2;
}

void ThreadClass::thread1()
{
    for(int i = 0; i < 100; i++)
    {
        rawdata = i;
        printf("生成数据: %d \n", rawdata);
        start = true;
        this_thread::sleep_for(std::chrono::milliseconds(1)); // 模拟读取硬件数据延时
    }
    start = false;
}

void ThreadClass::thread2()
{
    while(start)
    {
        unique_lock<mutex> lock(mtx);
        while(!readyfor_t2)
        {
            cv.wait(lock);
        }
        data = 2 * rawdata;
        printf("处理1: %d \n", data);
        this_thread::sleep_for(std::chrono::milliseconds(5)); // 模拟处理1耗费时间
        readyfor_t2 = false;
        cv.notify_all();
    }
}

void ThreadClass::thread3()
{
    while(start)
    {
        unique_lock<mutex> lock(mtx);
        while(readyfor_t2)
        {
            cv.wait(lock);
        }
        data = -1 * data;
        printf("处理2: %d \n", data);
        this_thread::sleep_for(std::chrono::milliseconds(5)); // 模拟处理2耗费时间
        readyfor_t2 = true;
        cv.notify_all();
    }
}

(3) main.cpp

#include "threadclass.hpp"
#include <iostream>
#include <thread>
using namespace std;
int main() {
    cout << "主线程启动: " << endl;
    ThreadClass tc{0, 0, false,true};
    thread t1(&ThreadClass::thread1, &tc);
    thread t2(&ThreadClass::thread2, &tc);
    thread t3(&ThreadClass::thread3, &tc);
    t1.join();
    t2.join();
    t3.join();

    return 0;
}

4. 实验结果

主线程启动: 
生成数据: 0 
处理1: 0 
生成数据: 1 
生成数据: 2 
生成数据: 3 
生成数据: 4 
处理2: 0 
生成数据: 5 
生成数据: 6 
生成数据: 7 
生成数据: 8 
生成数据: 9 
处理1: 18 
生成数据: 10 
生成数据: 11 
生成数据: 12 
生成数据: 13 
处理2: -18 
生成数据: 14 
生成数据: 15 
生成数据: 16 
生成数据: 17 
处理1: 34 
生成数据: 18 
生成数据: 19 
生成数据: 20 
生成数据: 21 
生成数据: 22 
处理2: -34 
生成数据: 23 
生成数据: 24 
生成数据: 25 
生成数据: 26 
生成数据: 27 
处理1: 54 
生成数据: 28 
生成数据: 29 
生成数据: 30 
生成数据: 31 
处理2: -54 
生成数据: 32 
生成数据: 33 
生成数据: 34 
生成数据: 35 
生成数据: 36 
处理1: 72 
生成数据: 37 
生成数据: 38 
生成数据: 39 
生成数据: 40 
处理2: -72 
生成数据: 41 
生成数据: 42 
生成数据: 43 
生成数据: 44 
生成数据: 45 
处理1: 90 
生成数据: 46 
生成数据: 47 
生成数据: 48 
生成数据: 49 
处理2: -90 
生成数据: 50 
生成数据: 51 
生成数据: 52 
生成数据: 53 
生成数据: 54 
处理1: 108 
生成数据: 55 
生成数据: 56 
生成数据: 57 
生成数据: 58 
生成数据: 59 
处理2: -108 
生成数据: 60 
生成数据: 61 
生成数据: 62 
生成数据: 63 
处理1: 126 
生成数据: 64 
生成数据: 65 
生成数据: 66 
生成数据: 67 
生成数据: 68 
处理2: -126 
生成数据: 69 
生成数据: 70 
生成数据: 71 
生成数据: 72 
处理1: 144 
生成数据: 73 
生成数据: 74 
生成数据: 75 
生成数据: 76 
生成数据: 77 
处理2: -144 
生成数据: 78 
生成数据: 79 
生成数据: 80 
生成数据: 81 
处理1: 162 
生成数据: 82 
生成数据: 83 
生成数据: 84 
生成数据: 85 
生成数据: 86 
处理2: -162 
生成数据: 87 
生成数据: 88 
生成数据: 89 
生成数据: 90 
生成数据: 91 
处理1: 182 
生成数据: 92 
生成数据: 93 
生成数据: 94 
生成数据: 95 
处理2: -182 
生成数据: 96 
生成数据: 97 
生成数据: 98 
生成数据: 99 
处理1: 198 

Process finished with exit code 0

5. 小结
为了实现这个功能,花了一天时间在网上试遍了各种博客里的方法,到我这不是死锁就是乱序.最后终于结合unique互斥锁和条件变量成功了.程序中线程函数里while()的判断应该可以改成cv.wait(lock, { … });的方式.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值