第13章 多线程程序设计
13.1线程的基本概念
线程是应用程序中的一条基本的执行路径,它 也是win32进程中的最小执行单元,线程由一个 堆栈、cpu寄存器的状态和系统调度列表中的一 个入口组成,每个线程都可以访问进程中的所有 资源。 一个进程由一个或多个线程、代码、数据和 应用程序在内存中的其他资源组成。低优先级的 线程一般要等待高优先级线程。一般每个线程相 互独立运行,各线程间应共享资源,然而必须通 过信号或其他进程内通信的方法来协调线程之间 的
工作。
使用线程可以在下面几个方面增强用户应用
程序 的性能: 1.避免瓶颈 2.并行操作 3.多处理器 13.1.1线程的优先级 每个线程的优先级由下面的标准决定: (1)其他进程的优先级类(高、普通或空闲)。 (2)其他进程优先级类中线程的优先级(最低、普 通下、普通、普通上、最高)。 (3)动态优先级增高,如果有的话,系统将在线程 的基础优先级上增加。
在创建线程时,用户并没有用数字为它们指 定优先级,系统将用两个步骤来确定线程的优先 级,第一步是给进程分配一个优先级类,进程的 优先级类将告诉
系统进程与系统中的其他进程相 对的优先级。第二步是为该进程所拥有的线程分 配相对优先级。 13.1.2 线程的同步 为了避免线程之间的冲突,有必要对访问共 享资源的线程进行同步控制设计,同步还可以使 线程之间相互依赖的代码能够正确运行。 Win32的API提供了如下一组可以使其句柄用 作同步的对象。
(1)同步对象:互斥对象(Mutext)、信号灯和事 件(Event)句柄 (2)文件句柄 (3)命令管道句柄 (4)控制台输入缓冲区句柄 (5)
通信设备句柄 (6)进程句柄 (7)线程句柄 13.1.3线程的局部存储(TLS) 线程的局部变量对运行此函数的各个线程是 局部的,但是当线程调用另一个函数时,该函数 使用的静态或全局变量对所有线程来说将是同样 的值。使用线程局部存储方法, 可通过对进程 中用于存储和获取各个线程不
同值的索引来完成对一个线程的存储分配。
13.2 定义线程对象
13.2.1 创建线程对象 要创建一个新的Tthread派生类,可以使用如 下步骤: (1)通过Delphi主菜单的【File】|【New】|【Other】 在弹出的【New Items】对话框中,选择 Tthread Objec图标,单击【OK】按钮,系统将 自动创建一个Tthread Object。 (2)系统弹出News Tthread Object对话框,在其中 输入一个新的类名和线程名。输入类名和线程名 之后,
Delphi将为用户创建一个用于实现线程的 新单元文件。
13.2.1 初始化线程对象 1.为线程指定一个优先级 但是也不能无休止的提高大量占用CPU的线 程的优先级,否则可能会导致其
他线程不能运行。 应该只为那些花费大量时间等待一个外部事件的 线程指定高优先级。 2.指定是否释放线程 最简单的方法是让线程自己释放。这种情况 下,可以将FreeOnTerminate属性值设为True。 然而,有时用户线程对象可能会代表一个应用程 序要反复执行的一个任务 。
13.2.3编写线程函数 使用主VCL线程 当用户使用VCL对象库中的对象时,他们的 属性和方法不能保证线程是安全的,也就是说, 访问属性或执行方法可能会执行一些使用了未受 保护的内存的操作。 如果所有对象在一个独立线程中访问它们的 属性和执行方法,用户就不必担心对象之间彼此 干扰,这时要使用主VCL线程,创建一个执行必 要操作的独立过程,然后在用户编程的 Synchronize方法中调用这个过程 。
在下述几种情况下,用户不需要使用 Synchronize方法: (1)数据访问组件是线程安全的。 (2)图形对象是线程安全的。 (3)当使用一个线程安全的TthreadList版本时。 1、使用线程局部变量 线程函数及其调用的任何过程都有自己的局 部变量。这些过程也可以访问全局变量。 有时用户可能要使用一些特殊变量,他们对 用