没有合适的资源?快使用搜索试试~ 我知道了~
用VC6实现Windows98下多线程编程技术.doc
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 103 浏览量
2022-07-07
08:21:50
上传
评论
收藏 188KB DOC 举报
温馨提示
试读
29页
用VC6实现Windows98下多线程编程技术
资源推荐
资源详情
资源评论
第 1 页 共 29 页
标 题: [转载] 用 VC6 实现 Windows98 下多线程编程技术
发信站: NJU Lily BBS (Fri Jun 18 16:50:13 1999), 转信
【 以下文字转载自 VC 讨论区 】
【 原文由 danger 所发表 】
注:这是本人的拙作,请高手指正!这本是一个 Word 文档,转化成 txt
文档后原来的一些格式丢失,如果想得到 word 文件,可与我联系.
// 注:本文连同原程序可在下面这个 FTP 服务器上得到:
ftp://panxiye.nju.eud.cn/incoming/multithread.zip
即 202.119.49.138,aqe 老兄的机器。
-----------东君,1999.6.18
另:文章所附的一些参考文献比较经典,可作详细学习所用.
用 VC6 实现 Windows98 下多线程编程技术
Multithread Programming Technique in Windows 98 Using VC6
摘 要
本文全面详尽的探讨了用 VC6 实现 Windows98 下多线程编程的技术。首先讨论
了线程的一些基本理论,包括线程的概念,优先级,以及同步问题。接着介绍了 VC6
中用 WIN32 API 函数库和 MFC 类库两种开发多线程应用程序的方法,分别包括线
程的创建,终止,设置和更改优先级,同步对象的使用等,线程同步是本文的重点。
本文还给出了两个编程实例--生产者消费者问题和五个哲学家吃通心粉问题。
关键词:进程 线程 多线程 优先级 同步 VC WIN32 API MF
目录
引言 1
1. 关于线程的讨论 1
1.1 WINDOWS98 下的多任务、多进程和多线程 1
1.2 进程与线程的优先级 1
1.3 线程同步 2
1.4 用 VISUAL C++6.0 开发 WINDOWS 应用程序的两种方法 3
2. 基于 WIN32 API 的多线程编程 3
2.1 编写线程函数 3
2.2 创建和终止线程 3
2.3 挂起和继续执行线程 4
2.4 关于优先级的操作 4
2.5 同步对象的使用 4
2.5.1 信号量(Semaphore) 5
2.5.2 互斥量(Mutex Semaphore) 5
第 2 页 共 29 页
2.5.3 事件(Event)对象 5
2.5.4 临界区(Critical Section) 6
2.5.5 可等待定时器(Waitable Timer) 6
2.6 创建一个新的进程 6
2.7 一个用 WIN32 API 进行多线程编程的实例--生产者与消费者问题 6
3. 基于 MFC 的多线程编程 9
3.1 MFC 类库对多线程的支持 9
3.2 工作者线程(WORKER THREAD)的创建 9
3.3 创建用户界面线程(USER INTERFACE THREAD) 10
3.4 MFC 线程同步类和同步访问类的使用 10
3.4.1 四种线程同步类的使用 10
3.4.2 同步访问类:CSingleLock 和 CMultipleLock 11
3.5 用 MFC 进行多线程编程的一个实例--五个哲学家吃通心粉问题 11
4. 结束语 14
参考文献 15
附录一:PCDEMO 程序 16
附录二:PHILOSOPHER 程序 22
用 VC6 实现 Windows98 下多线程编程技术
Multithread Programming Technique in Windows 98 Using VC6
引言
现代操作系统引入了线程的概念,多线程程序设计是一门崭新的技术。本文试
图全面详尽地探讨 Windows98 下的多线程编程技术,包括基于 WIN32 API 和基于
MFC 的两种不同的编程方法,着重探讨如何解决线程同步问题,并给出两个用 Visual
C++6.0 实现的多线程编程实例。
1. 关于线程的讨论
1.1 Windows98 下的多任务、多进程和多线程
Windows98 是一个多任务操作系统,它支持两种类型的多任务:基于进程(process)
的多任务和基于线程(thread)的多任务。进程是指正在执行的程序,在 Windows98 中
可以同时执行两个或多个任务进程,即运行多个程序,这就是普遍理解的基于进程
的多任务。
线程是指进程内的一条执行线路,或者说是进程中可执行代码的单独单元,它
是操作系统的基本调度单元。一个进程至少有一个线程,即主线程,也可以有多个
线程协同工作。进程从主线程开始执行,进而可以创建一个或多个附加线程来执行
该进程内的并发任务,这就是基于线程的多任务。
在 Windows98 中,每个 Win32 进程在独立的进程空间上运行,可以使用多达 4G
的线性地址空间。但进程本身是一个静态的概念,为了完成相应操作必须占有相应
的线程,正是线程负责执行包含在进程地址空间中的代码。一个进程内的所有线程
使用相同的 32 位线性地址空间,并共享所有的进程资源(包括打开的文件和动态分
配的内存),但每个线程有自己的堆栈和 CPU 寄存器,它们的执行由系统调度程序
控制。
基于线程的多任务允许一个程序的两个或多个部分同时执行,这样增加了程序
第 3 页 共 29 页
的维数,用户可以通过定义分离的执行线路来管理程序的执行,使编写出来的程序
更高效。例如,通常为后台计算创建一个线程。特别的,在多处理器系统中,多线
程可以极大地提高系统效率。
1.2 进程与线程的优先级
每个进程和线程都有相应的优先级设置,线程的优先级决定它何时运行和接收
多少 CPU 时间。最终的优先级共 32 级,是从 0 到 31 的数值,称为基本优先级别(base
priority level)。系统按照不同的优先级调度线程的运行。
0-15 级是普通优先级,线程的优先级可以动态变化,高优先级线程优先运行,
只有高优先级线程不运行时,才调度低优先级线程运行。优先级相同的线程按照时
间片轮流运行。
16-31 级是实时优先级,实时优先级与普通优先级的最大区别在于相同优先级线
程的运行不按照时间片轮转,而是先运行的线程就先控制 CPU,如果它不主动放弃
控制,同级或低优先级的线程就无法运行。
线程的实际优先级设置是两个值的结合:所属的进程的总优先级类和线程本身
的优先级别。一个线程的优先级首先属于一个类,然后是其在该类中的相对位置。
即:
线程优先级 = 进程优先级类 + 线程相对优先级
进程的优先级类从高到低如下(数字为基本优先级别数量):
REALTIME_PRIORITY_CLASS 24
HIGH_PRIORITY_CLASS 13
NORMAL_PRIORITY_CLASS 前台为 9,后台为 7
IDLE_PRIORITY_CLASS 4
进程的相对优先级:
THREAD_PRIORITY_LOWEST 比所在进程优先级低两个级别
THREAD_PRIORITY_BELOW_NORMAL 比所在进程优先级低一个级别
THREAD_PRIORITY_NORMAL 与进程同级
THREAD_PRIORITY_ABOVE_NORMAL 比所在进程优先级高一个级别
THREAD_PRIORITY_HIGHEST 比所在进程优先级高两个级别
HREAD_PRIORITY_IDLE 基本优先级为 1。对于
REALTIME_PRIORITY_CLASS 进程,优先级为 16
THREAD_PRIORITY_TIME_CRITICAL 基本优先级为 15。对于
REALTIME_PRIORITY_CLASS 进程,优先级别是 31。
在一般情况下,进程和线程的优先级被设置成 NORMAL_PRIORITY_CLASS 和
THREAD_PRIORITY_NORMAL,后面可以看到,程序运行时可以获取和更改进程
或线程的优先级。
1.3 线程同步
程序的并发执行往往带来与时间有关的错误,甚至引发灾难性的后果。这需要
引入同步机制。使用多进程与多线程时,有时需要协同两种或多种动作,此过程就
称同步(Synchronization)。引入同步机制的第一个原因是为了控制线程之间的资源
同步访问,因为多个线程在共享资源时如果发生访问冲突通常会带来不正确的后果。
例如,一个线程正在更新一个结构,同时另一个线程正试图读取同一个结构。结果,
第 4 页 共 29 页
我们将无法得知所读取的数据是新的还是旧的,或者是二者的混合。第二个原因是
有时要求确保线程之间的动作以指定的次序发生,如一个线程需要等待由另外一个
线程所引起的事件。
为了在多线程程序中解决同步问题,Windows98 提供了四种主要的同步对象,
每种对象相对于线程有两种状态——信号状态(signal state)和非信号状态(nonsignal
state)。当相关联的同步对象处于信号状态时,线程可以执行(访问共享资源),反
之必须等待。这四种同步对象是:
(1)事件对象(Event)。事件对象作为标志在线程间传递信号。一个或多个线
程可等待一个事件对象,当指定的事件发生时,事件对象通知等待线程可以开始执
行。它有两种类型:自动重置(auto-reset)事件和手动重置(manual-reset)事件。
(2)临界区(Critical Section)。临界区对象通过提供一个进程内所有线程必须
共享的对象来控制线程。只有拥有那个对象的线程可以访问保护资源。在另一个线
程可以访问该资源之前,前一个线程必须释放临界区对象,以便新的线程可以索取
对象的访问权。
(3)互斥量(Mutex Semaphore)。互斥量的工作方式非常类似于临界区,只是
互斥量不仅保护一个进程内为多个线程使用的共享资源,而且还可以保护系统中两
个或多个进程之间的的共享资源。
(4)信号量(Semaphore)。信号量可以允许一个或有限个线程访问共享资源。
它是通过计数器来实现的,初始化时赋予计数器以可用资源数,当将信号量提供给
一个线程时,计数器的值减 1,当一个线程释放它时,计数器值加 1。当计数器值小
于等于 0 时,相应线程必须等待。信号量是 Windows98 同步系统的核心。从本质上
讲,互斥量是信号量的一种特殊形式。
Windows98/NT 还提供了另外一种 Windows95 没有的同步对象:可等待定时器
(Waitable Timer)。它可以封锁线程的执行,直到到达某一具体时间。这可以用于
后台任务。
同步问题是多线程编程中最复杂的问题,本文后面将有详细的实现方法讨论。
1.4 用 Visual C++6.0 开发 Windows 应用程序的两种方法
用 VC++6 开发 Windows98 应用程序有两种方法,一种是利用 Win32 API 函数
编写 C 风格的 Win32 应用程序,另一种是利用 MFC(Microsoft Foundation Classes)
类库编写 C++风格的 Win32 应用程序。两种方法各有优缺点,基于 Win32 API 的应
用程序代码小巧,运行效率高,但开发难度较大;基于 MFC 的应用程序开发速度较
快,但代码很庞大。现在,用 MFC 类库进行开发越来越流行了。
这两种方法都可用来开发 Windows98 多线程应用程序,并且在原理上是一致的。
本文将分别讨论基于 Win32 API 的多线程编程和基于 MFC 的多线程编程。
2. 基于 Win32 API 的多线程编程
一个进程至少有一个线程,这个线程称为主线程。主线程可以创建一个或多个
辅助线程。Win32 API 函数库中提供了多线程控制函数,下面将予以讨论。
2.1 编写线程函数
每个线程的执行都起始于在进程内对线程函数的调用,线程函数就是新执行线
程的入口点(线程起始地址)。线程函数应具有下面的原型:
DWORD WINAPI MyThreadFunc(LPVOID param);
第 5 页 共 29 页
用户需要在自己的程序中编写这个函数。
2.2 创建和终止线程
任何线程都可以通过调用 WIN32 API 函数 CreateThread()来创建线程,其原型
如下:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性指针
DWORD dwStackSize,
// 堆栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 线程起始地址
LPVOID lpParameter,
// 传递给线程的参数
DWORD dwCreationFlags,
// 起始执行状态
LPDWORD lpThreadId);
// 线程 ID 指针
安全属性(lpThreadAttributes 指定)为 Windows NT 特有,Windows98 忽略,
选 NULL 即可;dwStackSize 如为 0,则堆栈大小与主线程相同;dwCreationFlags 有
两种情况,0 表示立即执行,CREATE_SUSPENDED 表示创建后被挂起,直到调用
ResumeThread()。该函数如果操作成功则返回线程的句柄,失败则返回 NULL。
线程被创建后,正常情况下就运行直到线程函数返回。用户也可调用下面两个
函数来终止线程:
VOID ExitThread(DWORD dwStatus); //dwStatus 为终止状态(
退出代码)
BOOL TerminateThread(HANDLE hThread, DWORD dwStatus);
ExitThread()将正常终止线程,一个线程函数如果调用 ExitThread()等价于使用
return 返回,系统将该线程从调度队列中删除,并复位堆栈。实际上,线程函数运
行到结尾或使用 return 时,系统自动调用 ExitThread()。
一个线程通过调用 TerminateThread()可以强迫另一个线程立刻停止,它第一个
参数指出了将被终止的线程的句柄。需要注意的是,它不释放线程占用的资源,不
做清除内存的操作,这样可能会引起系统不稳定。
如果多线程程序中使用了标准 C 库函数,并用 CreateThread()和 ExitThread(),
则会导致内存泄漏。解决这个问题的方法是用 C 运行库(run-time library)函数来启
动和终止线程,而不用 WIN32 API 定义的 CreateThread()和 ExitThread()。在 C 运行
库函数中,它们的替代函数分别是_beginthreadex()和_exitthreadex(),需要的头文件
是_process.h。在 VC6.0 下,还需在 Project->Settings->C/C++->Code Generation 中选
择 Multithreaded Runtime Library。当然,也可以通过避免使用 C 标准库函数的方法
来解决上述问题,WIN32 提供了一些 C 标准库函数的替代函数,例如,可用 wsprintf()
和 lstrlen()来代替 sprintf()和 strlen()。这样,使用 CreateThread()和 ExitThread()不会
出现问题。
2.3 挂起和继续执行线程
一个线程可以挂起和继续执行另外一个线程,使用的函数是:
DWORD SuspendThread(HANDLE hThread);
剩余28页未读,继续阅读
资源评论
oligaga
- 粉丝: 50
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- #P0015. 全排列 超级简单
- pta题库答案c语言之排序4统计工龄.zip
- pta题库答案c语言之树结构7堆中的路径.zip
- pta题库答案c语言之树结构3TreeTraversalsAgain.zip
- pta题库答案c语言之树结构2ListLeaves.zip
- pta题库答案c语言之树结构1树的同构.zip
- 基于C++实现民航飞行与地图简易管理系统可执行程序+说明+详细注释.zip
- pta题库答案c语言之复杂度1最大子列和问题.zip
- 三维装箱问题(Three-Dimensional Bin Packing Problem,3D-BPP)是一个经典的组合优化问题
- 以下是一些关于Linux线程同步的基本概念和方法.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功