多线程

C++中的类与多线程

标签(空格分隔): 学习笔记


背景:项目需求得把原来写的一个单线程版本改为多线程实现,已达到速度需求。原本的单线程版本已经封装好成类。

一、多线程的循环创建、申请、及使用

按照惯例,先贴代码:

//头文件
#include <process.h> 
//创建以及初始化锁
HANDLE hMutex;
hMutex = CreateMutex(NULL, FALSE, NULL);
//上锁
WaitForSingleObject(hMutex, INFINITE);
//解锁
ReleaseMutex(hMutex);
//循环开辟线程
//通过读取计算机的最大可用线程来开辟线程
    const int num_threads = 8;
    HANDLE handle[num_threads];
    for (int i = 0; i < num_threads; i++)
    {
        //HANDLE handle = INVALID_HANDLE_VALUE;
        unsigned int id[num_threads] = { 0 };
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, singleChannelFunc, this, 0, &id[i]);

    }
    WaitForMultipleObjects(num_threads, handle, true, INFINITE);
    for (int i = 0; i < num_threads; i++)
    {
        CloseHandle(handle[i]);
    }

其中,开辟线程的数目可有自己的程序需求而定,当然如果你需要的线程越多越好,那么下面这个函数可以帮你获取到此台计算机当中最大可用线程,包含头文件”windows.h”

static int get_processor_number()
{
    SYSTEM_INFO info;
    GetSystemInfo(&info);
    return (int)info.dwNumberOfProcessors;

}

二、类和多线程之间的调用关系

详细步骤:
1、在开辟线程之前先维护一个队列,该队列存放需要分发给各单个线程的数据信息。(针对我的项目来说,将图像块的起始点位置ij以及图像块的长宽hw存放在队列里面)更为具体的来说,单线程的程序中,分配好图像块之后调用的执行参数压到队列里面。
单线程程序

class A;
//分块
for(int i = 0;i < rows_num;i++)
{
    for(int j = 0;j  < cols_num ;j++)
    {
        i_idx = blk.col * i;
        j_idx = blk.row * j;
        A.run(i_idx,j_idx,blk.row.blk.col);
    }

}

改写为相应的多线程部分

class Para
{
    para1;
    para2;
    para3;
    para4;
}

//维护队列
queue <class Para> queue_img_info;

//分块
for(int i = 0;i < rows_num;i++)
{
    for(int j = 0;j  < cols_num ;j++)
    {
        i_idx = blk.col * i;
        j_idx = blk.row * j;
        Para parameter;
        parameter.para1 = i_idx;
        parameter.para2 = j_idx;
        parameter.para3 = blk.row;
        parameter.para4 = blk.col;
        queue_img_info.push(parameter);
    }
}

2、写多线程调用的类内部接口方法和外部单线程工作的接口函数
由于语法的规定,单个线程的执行函数的输入参数必须是void*,则单线程的函数只需要做两件事情:将void*的输入强制类型转换为A*,然后调用A*类的内部多线程接口方法;
外部接口函数,只需要定义每个单个线程需要干什么事就行

unsigned int _stdcall singleChannelFunc(void * pm)
{
    A *ptr_solver = static_cast<A*>(pm);
    ptr_solver->singleChanFunInterface();
    return 0;
}

A类内部的多线程接口函数,它需要规定线程锁定释放的顺序

void APSR_solver::singleChanFunInterface()
{
    while (1)
    {
        //有线程进来,立马上锁
        WaitForSingleObject(hMutex, INFINITE);
        //如果队列为空,代表当前没有任务需要进行处理,立马开锁
        if (queue_img_info.empty())
        {
            ReleaseMutex(hMutex);
            break;
        }
        //单个线程获得队列信息
        Para para = queue_img_info.front();
        //将处理的队列中的第一块拿走
        queue_img_info.pop();
        //开锁
        ReleaseMutex(hMutex);
        //执行单线程任务(A)
        run(para.para1,para.para2,para.para3,para.para4);
    }
}

3、在类中的执行函数中开辟线程,其中每个线程都调用单线程函数

    //开辟线程
    const int num_threads = 8;
    //定义线程句柄
    HANDLE handle[num_threads];
    for (int i = 0; i < num_threads; i++)
    {
        unsigned int id[num_threads] = { 0 };
        //将每个线程都关联类外的单线程函数,冰纯如this指针
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, singleChannelFunc, this, 0, &id[i]);
    }
    //等待多线程执行任务
    WaitForMultipleObjects(num_threads, handle, true, INFINITE);
    //循环关闭句柄
    for (int i = 0; i < num_threads; i++)
    {
        CloseHandle(handle[i]);
    }

以上就是将一个封装好的类中的单线程方法改实现为多线程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值