Windows平台下的多线程编程

pthread-win32:跨平台多线程编程在Windows的实现 在现代操作系统中,多线程编程已成为实现应用程序并行化、提高系统效率和响应速度的关键技术。POSIX线程(pthreads),作为一套定义了线程行为的API标准,广泛应用于UNIX、Linux、以及POSIX兼容的系统上。通过pthreads,开发者能够利用多线程的能力来改善程序的性能与用户体验。是一个为Windows系统提供的POSIX线程库的安装程序。它允许开发者在Windows平台上使用POSIX线程API进行多线程编程,以模拟UNIX环境的线程行为。 阅读详情

线程是进程的一条执行路径,它包含独立的堆栈和CPU寄存器状态,每个线程共享所有的进程资源,包括打开的文件、信号标识及动态分配的内存等。一个进程内的所有线程使用同一个地址空间,而这些线程的执行由系统调度程序控制,调度程序决定哪个线程可执行以及什么时候执行线程。线程有优先级别,优先权较低的线程必须等到优先权较高的线程执行完后再执行。在多处理器的机器上,调度程序可将多个线程放到不同的处理器上去运行,这样可使处理器任务平衡,并提高系统的运行效率。

Windows是一种多任务的操作系统,在Windows的一个进程内包含一个或多个线程。32位Windows环境下的Win32 API提供了多线程应用程序开发所需要的接口函数,而利用VC中提供的标准C库也可以开发多线程应用程序,相应的MFC类库封装了多线程编程的类,用户在开发时可根据应用程序的需要和特点选择相应的工具。为了使大家能全面地了解Windows多线程编程技术,本文将重点介绍Win32 API和MFC两种方式下如何编制多线程程序。

多线程编程在Win32方式下和MFC类库支持下的原理是一致的,进程的主线程在任何需要的时候都可以创建新的线程。当线程执行完后,自动终止线程; 当进程结束后,所有的线程都终止。所有活动的线程共享进程的资源,因此,在编程时需要考虑在多个线程访问同一资源时产生冲突的问题。当一个线程正在访问某进程对象,而另一个线程要改变该对象,就可能会产生错误的结果,编程时要解决这个冲突。

Win32 API下的多线程编程

Win32 API是Windows操作系统内核与应用程序之间的界面,它将内核提供的功能进行函数包装,应用程序通过调用相关函数而获得相应的系统功能。为了向应用程序提供多线程功能,Win32 API函数集中提供了一些处理多线程程序的函数集。直接用Win32 API进行程序设计具有很多优点: 基于Win32的应用程序执行代码小,运行效率高,但是它要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源。用Win32 API直接编写程序要求程序员对Windows系统内核有一定的了解,会占用程序员很多时间对系统资源进行管理,因而程序员的工作效率降低。

1. 用Win32函数创建和终止线程

Win32函数库中提供了操作多线程的函数,包括创建线程、终止线程、建立互斥区等。在应用程序的主线程或者其他活动线程中创建新的线程的函数如下:

HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);

如果创建成功则返回线程的句柄,否则返回NULL。创建了新的线程后,该线程就开始启动执行了。但如果在dwCreationFlags中使用了CREATE_SUSPENDED特性,那么线程并不马上执行,而是先挂起,等到调用ResumeThread后才开始启动线程,在这个过程中可以调用下面这个函数来设置线程的优先权:

BOOL SetThreadPriority(HANDLE hThread,int nPriority);

当调用线程的函数返回后,线程自动终止。如果需要在线程的执行过程中终止则可调用函数:

VOID ExitThread(DWORD dwExitCode);

如果在线程的外面终止线程,则可调用下面的函数:

BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);

但应注意: 该函数可能会引起系统不稳定,而且线程所占用的资源也不释放。因此,一般情况下,建议不要使用该函数。

如果要终止的线程是进程内的最后一个线程,则线程被终止后相应的进程也应终止。

2. 线程的同步

在线程体内,如果该线程完全独立,与其他线程没有数据存取等资源操作上的冲突,则可按照通常单线程的方法进行编程。但是,在多线程处理时情况常常不是这样,线程之间经常要同时访问一些资源。由于对共享资源进行访问引起冲突是不可避免的,为了解决这种线程同步问题,Win32 API提供了多种同步控制对象来帮助程序员解决共享资源访问冲突。在介绍这些同步对象之前先介绍一下等待函数,因为所有控制对象的访问控制都要用到这个函数。

Win32 API提供了一组能使线程阻塞其自身执行的等待函数。这些函数在其参数中的一个或多个同步对象产生了信号,或者超过规定的等待时间才会返回。在等待函数未返回时,线程处于等待状态,此时线程只消耗很少的CPU时间。使用等待函数既可以保证线程的同步,又可以提高程序的运行效率。最常用的等待函数是:

DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

而函数WaitForMultipleObject可以用来同时监测多个同步对象,该函数的声明为:

DWORD WaitForMultipleObject(DWORD nCount,CONST HANDLE *lpHandles,BOOL bWaitAll,DWORD dwMilliseconds);

(1)互斥体对象

Mutex对象的状态在它不被任何线程拥有时才有信号,而当它被拥有时则无信号。Mutex对象很适合用来协调多个线程对共享资源的互斥访问。可按下列步骤使用该对象:

首先,建立互斥体对象,得到句柄:

HANDLE CreateMutex();

然后,在线程可能产生冲突的区域前(即访问共享资源之前)调用WaitForSingleObject,将句柄传给函数,请求占用互斥对象:

dwWaitResult = WaitForSingleObject(hMutex,5000L);

共享资源访问结束,释放对互斥体对象的占用:

ReleaseMutex(hMutex);

互斥体对象在同一时刻只能被一个线程占用,当互斥体对象被一个线程占用时,若有另一线程想占用它,则必须等到前一线程释放后才能成功。

(2)信号对象

信号对象允许同时对多个线程共享资源进行访问,在创建对象时指定最大可同时访问的线程数。当一个线程申请访问成功后,信号对象中的计数器减一,调用ReleaseSemaphore函数后,信号对象中的计数器加一。其中,计数器值大于或等于0,但小于或等于创建时指定的最大值。如果一个应用在创建一个信号对象时,将其计数器的初始值设为0,就阻塞了其他线程,保护了资源。等初始化完成后,调用ReleaseSemaphore函数将其计数器增加至最大值,则可进行正常的存取访问。可按下列步骤使用该对象:

首先,创建信号对象:

HANDLE CreateSemaphore();

或者打开一个信号对象:

HANDLE OpenSemaphore();

然后,在线程访问共享资源之前调用WaitForSingleObject。

共享资源访问完成后,应释放对信号对象的占用:

ReleaseSemaphore();

(3)事件对象

事件对象(Event)是最简单的同步对象,它包括有信号和无信号两种状态。在线程访问某一资源之前,需要等待某一事件的发生,这时用事件对象最合适。例如:只有在通信端口缓冲区收到数据后,监视线程才被激活。

事件对象是用CreateEvent函数建立的。该函数可以指定事件对象的类和事件的初始状态。如果是手工重置事件,那么它总是保持有信号状态,直到用ResetEvent函数重置成无信号的事件。如果是自动重置事件,那么它的状态在单个等待线程释放后会自动变为无信号的。用SetEvent可以把事件对象设置成有信号状态。在建立事件时,可以为对象命名,这样其他进程中的线程可以用OpenEvent函数打开指定名字的事件对象句柄。

(4)排斥区对象

在排斥区中异步执行时,它只能在同一进程的线程之间共享资源处理。虽然此时上面介绍的几种方法均可使用,但是,使用排斥区的方法则使同步管理的效率更高。

使用时先定义一个CRITICAL_SECTION结构的排斥区对象,在进程使用之前调用如下函数对对象进行初始化:

VOID InitializeCriticalSection(LPCRITICAL_SECTION);

当一个线程使用排斥区时,调用函数:EnterCriticalSection或者TryEnterCriticalSection;

当要求占用、退出排斥区时,调用函数LeaveCriticalSection,释放对排斥区对象的占用,供其他线程使用。

基于MFC的多线程编程

MFC是微软的VC开发集成环境中提供给程序员的基础函数库,它用类库的方式将Win32 API进行封装,以类的方式提供给开发者。由于其快速、简捷、功能强大等特点深受广大开发者喜爱。因此,建议使用MFC类库进行应用程序的开发。

在VC++附带的MFC类库中,提供了对多线程编程的支持,基本原理与基于Win32 API的设计一致,但由于MFC对同步对象做了封装,因此实现起来更加方便,避免了对象句柄管理上的烦琐工作。

在MFC中,线程分为两种:工作线程和用户接口线程。工作线程与前面所述的线程一致,用户接口线程是一种能够接收用户的输入、处理事件和消息的线程。

1. 工作线程

工作线程编程较为简单,设计思路与前面所讲的基本一致: 一个基本函数代表了一个线程,创建并启动线程后,线程进入运行状态; 如果线程用到共享资源,则需要进行资源同步处理。这种方式创建线程并启动线程时可调用函数:

CWinThread*AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam,int nPriority= THREAD_PRIORITY_NORMAL,UINT nStackSize =0,DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);参数pfnThreadProc是线程执行体函数,函数原形为: UINT ThreadFunction( LPVOID pParam)。

参数pParam是传递给执行函数的参数;

参数nPriority是线程执行权限,可选值:

THREAD_PRIORITY_NORMAL、THREAD_PRIORITY_LOWEST、THREAD_PRIORITY_HIGHEST、THREAD_PRIORITY_IDLE。

参数dwCreateFlags是线程创建时的标志,可取值CREATE_SUSPENDED,表示线程创建后处于挂起状态,调用ResumeThread函数后线程继续运行,或者取值“0”表示线程创建后处于运行状态。

返回值是CWinThread类对象指针,它的成员变量m_hThread为线程句柄,在Win32 API方式下对线程操作的函数参数都要求提供线程的句柄,所以当线程创建后可以使用所有Win32 API函数对pWinThread->m_Thread线程进行相关操作。

注意:如果在一个类对象中创建和启动线程时,应将线程函数定义成类外的全局函数。

2. 用户接口线程

基于MFC的应用程序有一个应用对象,它是CWinApp派生类的对象,该对象代表了应用进程的主线程。当线程执行完并退出线程时,由于进程中没有其他线程存在,进程自动结束。类CWinApp从CWinThread派生出来,CWinThread是用户接口线程的基本类。我们在编写用户接口线程时,需要从CWinThread派生我们自己的线程类,ClassWizard可以帮助我们完成这个工作。

先用ClassWizard派生一个新的类,设置基类为CwinThread。注意:类的DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏是必需的,因为创建线程时需要动态创建类的对象。根据需要可将初始化和结束代码分别放在类的InitInstance和ExitInstance函数中。如果需要创建窗口,则可在InitInstance函数中完成。然后创建线程并启动线程。可以用两种方法来创建用户接口线程,MFC提供了两个版本的AfxBeginThread函数,其中一个用于创建用户接口线程。第二种方法分为两步进行:首先,调用线程类的构造函数创建一个线程对象;其次,调用CWinThread::CreateThread函数来创建该线程。线程建立并启动后,在线程函数执行过程中一直有效。如果是线程对象,则在对象删除之前,先结束线程。CWinThread已经为我们完成了线程结束的工作。

3. 线程同步

前面我们介绍了Win32 API提供的几种有关线程同步的对象,在MFC类库中对这几个对象进行了类封装,它们有一个共同的基类CSyncObject,它们的对应关系为: Semaphore对应CSemaphore、Mutex对应CMutex、Event对应CEvent、CriticalSection对应CCriticalSection。另外,MFC对两个等待函数也进行了封装,即CSingleLock和CMultiLock。因四个对象用法相似,在这里就以CMutex为例进行说明:

创建一个CMutex对象:

CMutex mutex(FALSE,NULL,NULL);

或CMutex mutex;

当各线程要访问共享资源时使用下面代码:

CSingleLock sl(&mutex);

sl.Lock();

if(sl.IsLocked())

//对共享资源进行操作...

sl.Unlock();

结束语

如果用户的应用程序需要多个任务同时进行相应的处理,则使用多线程是较理想的选择。这里,提醒大家注意的是在多线程编程时要特别小心处理资源共享问题以及多线程调试问题.

工业视觉实战:用摄像头+AI高精度测量钢板尺寸(附深度分析) 摘要: 钢铁制造业正加速采用基于摄像头与深度学习的视觉测量技术,以取代传统人工测量,实现钢板长、宽、高(厚)的非接触、高精度在线检测。核心方案包括单目视觉(低成本但受限于变形)、双目/多目立体视觉(可精确测量变形钢板)及3D激光扫描(微米级精度)。系统精度受硬件(相机分辨率、镜头)、算法(亚像素技术)及环境稳定性共同影响,综合精度可达±0.1mm。实战中需重点解决热膨胀(需红外测温实时补偿)和钢板变形(必须采用三维方案)两大挑战,并通过工程化设计(散热、防振)确保系统可靠运行。该技术需融合光学、机械与算法, 阅读详情

相关推荐

CMAC算法原理

2、K1 通过以下运算导出:若 L 的最高有效位等于 0,则 K1 是 L 的左移 1 位。3、K2 通过如下运算导出:若 K1 的最高有效位等于 0,则 K2 是 K1 的左移 1 位。采用了 AES 算法中的类似 CBC 模式的加密方式,即对前一个分组的密文与当前分组的明文进行异或操作后在加密,2、分块处理:首先将消息分成多个固定长度的块,若消息长度不是块大小的倍数,则可以使用填充来将其填充到合适的大小。1、子密钥计算,通过主密钥生成子密钥(key1,key2),子密钥用于最后一个块处理;

sky的博客 1659

多线程编程

 下载源代码一、问题的提出编写一个耗时的单线程程序:  新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下: void CSingleThreadDlg::OnSleepSixSecond() { Sl

不论你在什么时候开始,重要的是开始之后就不要停止。 1575

synopsys工具安装系列(一)安装installer

synopsys为eda工具安装,提供了一个安装器,名叫installer。所以,首先要先安装installer这个工具,之后才能安装其他的eda工具。 首先从官网下载该installer工具。我这里下载的是5.2版本 下载之后,有如下安装文件。 将该安装包,拷贝到linux服务器中。 首先给SynopsysInstaller_v5.2.run赋予可执行权限。 chmod a+x SynopsysInstaller_...

weiqi7777的博客 8394

内存分配与跟踪

需求分析 编写一个程序,包括两个线程,一个线程用于模拟内存分配活动,另一个用于跟踪第一个线程的内存行为,要求两个线程之间通过信号量实现同步,模拟内存活动的线程可以从一个文件中读出要进行的内存操作。每个内存操作包含如下内容: 时间:每个操作等待时间; 块数:分配内存的粒度; 操作:包括保留一个区域、提交一个区域、释放一个区域、回收一个区域、加锁与解锁一个区域。可将它们的编号放置于一个文件...

清欢Viki的博客 1317

手把手教你用Simulink+CANoe+Carsim搭建硬件在环仿真环境(避坑指南)

本文是一份详细的硬件在环仿真环境搭建指南,重点讲解如何将Simulink、CANoe和CarSim三大工具进行实战融合。内容涵盖软件版本兼容性、授权避坑、环境配置,并分步演示了从离线联合仿真到实现软实时同步的完整流程,旨在帮助汽车电子工程师高效构建稳定的HIL测试平台。

weixin_29092579的博客 407

高效爬取懂车帝车型数据:从静态解析到动态反爬实战

本文详细解析了如何高效爬取懂车帝车型数据,从静态HTML解析到动态接口反爬的完整实战路径。文章重点介绍了使用浏览器开发者工具定位数据、应对CSS混淆与参数加密等反爬策略,并提供了整合静态与动态抓取逻辑的Python代码示例,帮助开发者稳健地获取结构化车型信息。

wind6的博客 937

关于线程的面试题

1:什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。Java在语言层面对多线程提供了卓越的支持,它也是一个很好的卖点。欲了解更多详细信息请点击这里。 2:线程和进程有什么区别? ...

aikong3218的博客 195

【NAS for PVE _04】安装TrueNAS

前篇说到如何调试 Proxmox VE 8.2 为安装虚拟机做准备,本篇主要讲述如何在 Proxmox VE 上安装 TrueNAS 系统,并开启NFS供其他系统挂载使用官网下载好TrueNAS系统镜像。

村口王师傅。 6146

VC创建线程

VC创建线程

ffghggf的博客 2889

基于R-CNN深度学习的常见手势识别系统:数据集、模型和UI界面的完整实现

卷积神经网络(CNN):用于从图像中提取特征。区域提议网络(RPN):用于生成可能包含手势的候选区域。:将候选区域调整为固定大小,并进行进一步的分类和回归。接下来,我们需要加载一个预训练的Faster R-CNN模型,并对其进行微调。我们将使用# 加载预训练的Faster R-CNN模型# 获取分类器的输入特征数# 替换分类器头部,设置为我们数据集的类别数(假设有5类手势)

YOLO 1001

从 SEGW 到 SADL 的那根线,彻底理解 OData Data Source Mapping

本文摘要(150字): 在SAP Gateway的SADL型OData服务开发中,"Map to Data Source"是关键配置环节。与传统RFC映射不同,SADL映射不是针对单个CRUDQ操作,而是建立OData模型与SADL业务实体间的完整语义对应关系。通过属性映射和关联映射,系统能自动处理数据获取和导航请求。映射编辑器支持三种模式:属性映射处理字段对应,关联映射处理模型间关系,动作映射处理业务操作。映射的本质是建立语义翻译表,决定了后续OData请求如何转化为后端业务实体访问,而非简单的字段重命名

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 63

Windows平台上多线程编程与互斥锁

Windows平台上多线程编程 多线程(multithreading)是一种并发编程的方式,它允许程序同时执行多个任务。 1.功能 并发执行:多线程技术使得一个程序能够同时运行多个任务,这些任务在逻辑上相互独立,但在执行过程中可能共享某些资源。 资源共享:在多线程程序中,多个线程可以访问共享的内存空间,这些共享资源包括变量、数据结构等。 同步与互斥:为了保证多线程程序的正确性和效率,需要实现线程之间的同步和互斥,以避免数据竞争和死锁等问题。

热土程序园,利他愉己~ 1695

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2660

Windows平台pthread库使用指南:提升多线程编程效率的不二选择

Windows平台pthread库使用指南:提升多线程编程效率的不二选择 去发现同类优质开源项目:https://gitcode.com/ 在当今软件开发领域,多线程编程已成为提升程序性能和响应速度的关键技术。然而,在Windows平台上进行多线程编程,往往需要面对诸多挑战。今天,我将为您推荐一个开源项目——Windows平台pthread库使用指南,它将助您在Windows环境下轻松应对这些挑战...

gitblog_06718的博客 633

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【亲测免费】 在Windows平台上轻松实现多线程编程:pthreads-win32资源文件推荐

在Windows平台上轻松实现多线程编程:pthreads-win32资源文件推荐 【下载地址】pthreads-win32资源文件下载 本仓库提供了一个名为 `pthreads-win32` 的资源文件下载。该资源文件包含了在 Windows 平台上使用 pthreads 所需的 DLL、头文件和库文件 ...

gitblog_09728的博客 428

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Windows下可用的pthread库:为多线程编程提供跨平台解决方案

Windows下可用的pthread库:为多线程编程提供跨平台解决方案 去发现同类优质开源项目:https://gitcode.com/ 在多线程编程领域,拥有一套稳定且兼容性强的库至关重要。Windows下可用的pthread库,不仅为开发者解决了跨平台编程的难题,还提升了开发效率和软件性能。下面,我们将详细介绍这个项目的核心功能、技术特点和应用场景。 项目介绍 Windows下可用的pthre...

gitblog_06721的博客 269

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Windows平台下的多线程编程【转】

528
上一篇: 删除目录及目录下所有文件与子目录
下一篇: Visual C++编程中的文件操作
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值