多线程

来源:互联网 发布:linux echo是什么意思 编辑:程序博客网 时间:2024/05/21 06:45

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
原创粉丝点击