Win32多线程类

本文介绍了如何在Win32环境下编写多线程类,通过使用CUDA进行三维配准但效果不佳,转向使用CPU多线程进行并行计算。文章详细讲解了如何创建线程、线程同步,以及遇到的问题和解决方案,包括线程函数必须是全局函数的限制和线程同步的实现,最后展示了带有线程同步的完整代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Win32 多线程类

       前些时候用 CUDA 做了个加速三维配准的程序,做的结果很是让人郁闷,在一个四核 CPU 9600GT 显卡上运行的速度差不多,偏偏对方又规定了不能换更高档的显卡,于是决定改用 CPU 多线程来做并行计算,结果还不错,于是把程序写成了 win32 多线程的类,封装在 DLL 中。下面介绍一下怎么写多线程的类,如果有错误的话希望大家指正。

 

       首先是关于 Win32 多线程的一些基本知识,包括线程创建和同步等,更详细的内容大家可以在清华大学出版社的《多核程序设计》中找到。对多线程编程有过初步了解的可以直接跳过这一部分。

       Win32 API 中用于创建线程的主要有两个函数,一个是定义在 Windows.h 中的 CreateThread ,另外一个是定义在 process.h 中的 _beginthread 函数。这里我用的是形式比较简单的 _beginthread 函数。

线程同步主要以下面几种方式实现:全局变量,事件,临界区,互斥量和信号量,采用哪种方式取决于要用多线程做什么。例如用事件做线程同步的话,需要调用 CreateEvent WaitForSingleObject 两个函数。

另外,还可以用 SetThreadPriority 设置线程的优先级,用 SuspendThread ResumeThread 挂起和恢复线程,用 WaitForSingleObject WaitForMultipleObject 实现线程等待,用 ExitThread TerminateThread 强制终止线程。

 

在了解了多线程编程以后,就可以继续讲封装了多线程的类的编写了。

首先新建一个空的 Win32 控制台应用程序,用类向导在其中添加一个名为 CMThread 的类,类的代码如下:

//MThread.h

#pragma once

 

class CMThread

{

public :

     CMThread (void );

public :

     ~CMThread (void );

 

public :

     void Run ();                 // 创建线程

 

private :

     int a ;

     int b ;

 

private :

     void ThreadA (LPVOID pParam );              // 线程A 的线程函数

     void ThreadB (LPVOID pParam );              // 线程B 的线程函数

};

 

//MThread.cpp

#include "MThread.h"

#include <iostream>

#include <process.h>

using namespace std ;

 

CMThread ::CMThread (void )

{

     a = 0;

     b = 1;

}

 

CMThread ::~CMThread (void )

{

}

 

void CMThread ::ThreadA (LPVOID pParam )

{

     cout <<" 线程" <<a <<" 调用成功" <<endl ;

}

 

void CMThread ::ThreadB (LPVOID pParam )

{

     cout <<" 线程" <<b <<" 调用成功" <<endl ;

}

 

// 创建线程

void CMThread ::Run ()

{

     _beginthread (ThreadA , 0, NULL );

     _beginthread (ThreadB , 0, NULL );

}

为了测试多线程类,还需要添加一个 main.cpp 文件:

//main.cpp

#include "MThread.h"

#include <iostream>

 

void main ()

{

     CMThread mtThread ;

     mtThread .Run ();

}

 

编译程序,会出现如下错误:

error C3867: 'CMThread::ThreadA': function call missing argument list; use '&CMThread::ThreadA' to create a pointer to member

error C3867: 'CMThread::ThreadB': function call missing argument list; use '&CMThread::ThreadB' to create a pointer to member

 

双击错误,会发现是 _beginthread(ThreadA, 0, NULL) 出错,如果只是从字面上理解,似乎是因为函数指针调用方式错误引起的,但是将 ThreadA 换成 &CMThread::ThreadA 时仍然不能运行成功。其实这是因为线程函数必须是全局函数。为此需要将线程声明为 static 函数。这时候又会出现一个新的问题: static 类型的函数中不能访问类中其它的非静态成员 ! 解决这个问题的一种方法是将线程函数中用到的类成员函数和变量都声明为 static 型,但是这种方法显然不实用。另外一种方法是将类本身作为参数传递到线程函数中,为此,需要对线程函数和 Run 函数作如下修改:

void CMThread ::ThreadA (LPVOID pParam )

{

     CMThread *mt = (CMThread *)pParam ;

 

     cout <<" 线程" <<mt ->a <<" 调用成功" <<endl ;

 

}

 

void CMThread ::ThreadB (LPVOID pParam )

{

     CMThread *mt = (CMThread *)pParam ;

     cout <<" 线程" <<mt ->b <<" 调用成功" <<endl ;

 

}

 

// 创建线程

void CMThread ::Run ()

{

 

     _beginthread (ThreadA , 0, this );

     _beginthread (ThreadB , 0, this );

}

 

这个时候再运行程序就不会报错了,但是多运行几次就会发现,每次运行输出的结果只有一半或是完全没有输出 ( 如下图所示 ) 。原来是线程没有同步。

加上线程同步后的代码如下:

//MThread.h

#pragma once

 

#include <Windows.h>

#include <process.h>

 

class CMThread

{

public :

     CMThread (void );

public :

     ~CMThread (void );

 

public :

     void Run ();                 // 创建线程

 

private :

     int a ;

     int b ;

     HANDLE evThreadAOver ;       // 用于标识线程A 结束的事件

     HANDLE evThreadBOver ;       // 用于标识线程B 结束的事件

 

private :

     static void ThreadA (LPVOID pParam );            // 线程A 的线程函数

     static void ThreadB (LPVOID pParam );            // 线程B 的线程函数

};

 

 

//MThread.cpp

#include "MThread.h"

#include <iostream>

using namespace std ;

 

CMThread ::CMThread (void )

{

     a = 0;

     b = 1;

}

 

CMThread ::~CMThread (void )

{

}

 

void CMThread ::ThreadA (LPVOID pParam )

{

     CMThread *mt = (CMThread *)pParam ;

 

     cout <<" 线程" <<mt ->a <<" 调用成功" <<endl ;

 

     SetEvent (mt ->evThreadAOver );

}

 

void CMThread ::ThreadB (LPVOID pParam )

{

     CMThread *mt = (CMThread *)pParam ;

     cout <<" 线程" <<mt ->b <<" 调用成功" <<endl ;

 

     SetEvent (mt ->evThreadBOver );

}

 

// 创建线程

void CMThread ::Run ()

{

     // 产生事件

     evThreadAOver = CreateEvent (NULL , FALSE , FALSE , NULL );

     evThreadBOver = CreateEvent (NULL , FALSE , FALSE , NULL );

 

     // 创建线程AB

     _beginthread (ThreadA , 0, this );

     _beginthread (ThreadB , 0, this );

 

     // 等待线程AB 结束

     WaitForSingleObject (evThreadAOver , INFINITE );

     WaitForSingleObject (evThreadBOver , INFINITE );

}

 

 

//main.cpp

#include "MThread.h"

#include <iostream>

 

void main ()

{

     CMThread mtThread ;

     mtThread .Run ();

}

 

运行结果如图所示

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值