delphi线程对象tthread

上传人:xiao****1972 文档编号:83804355 上传时间:2019-03-01 格式:DOCX 页数:10 大小:29.08KB
返回 下载 相关 举报
delphi线程对象tthread_第1页
第1页 / 共10页
delphi线程对象tthread_第2页
第2页 / 共10页
delphi线程对象tthread_第3页
第3页 / 共10页
delphi线程对象tthread_第4页
第4页 / 共10页
delphi线程对象tthread_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《delphi线程对象tthread》由会员分享,可在线阅读,更多相关《delphi线程对象tthread(10页珍藏版)》请在金锄头文库上搜索。

1、多线程的基本概念和Delphi线程对象Tthread介绍WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行时间和资源,或者说,把CPU时间划成片,每个片分给不同的线程,这样,每个线程轮流的“挂起”和“唤醒”,由于时间片很小,给人的感觉是同时运行的。多线程带来如下好处:1)避免瓶颈;2)并行操作;3)提高效率;多线程的两个概念:1)进程:也称任务,程序载入内存,并分配资源,称为“一个进程”。注意:进程本身并不一定要正在执行。进程由以下几部分组成:a一个私有的地址空间,它是进程可以使用的一组虚拟内存地址空间;b程序的相关代码、数据源

2、;c系统资源,比如操作系统同步对象等;d至少包含一个线程(主线程);2)线程:是进程的执行单位(线程本身并不包括程序代码,真正拥有代码的是进程),是操作系统分配CPU时间的基本实体,每个进程至少包括一个线程,称为主线程。一个进程如果有多个线程,就可以共享同一进程的资源,并可以并发执行。通俗点说就是进程中一段并发运行的代码(一个函数或过程)。线程主要由如下两部分组成:a数据结构;bCPU寄存器和堆栈;线程函数运行,启动函数就返回了,主线程继续向下执行,而线程函数在一个独立的线程中执行,它要执行多久,什么时候返回,主线程是不管也不知道的。一、Delphi线程对象-Tthread虽然Windows提

3、供了较多的多线程设计的API函数,但是直接使用API函数极其不方便,而且使用不当还容易出错。为解决这个问题,Borland公司率先推出了一种Tthread对象,来解决多线程设计上的困难,简化了多线程问题的处理。一、Tthread对象的主要方法构造线程:constructor Create(CreateSuspended:boolean)CreateSuspended=true构造但不唤醒;false构造的同时即唤醒。挂起线程:suspend:(把线程挂起的次数加一)唤醒线程:resume:(注意:注意这个属性是把线程挂起的次数减一,当次数为0时,即唤醒。也就是说,线程挂起多少次,唤醒也需要多少

4、次。同时挂起的时候将保持线程的地址指针不变,所以线程挂起后再唤醒,将从挂起的地方开始运行)析构(清除线程所占用的内存):destroy终止线程Terminate使用这个类也很简单,基本用法是:先从TThread派生一个自己的线程类(因为TThread是一个抽象类,不能生成实例),然后是覆盖(Override)抽象方法:Execute(这就是线程函数,也就是在线程中执行的代码部分),如果需要用到可视VCL对象,还需要通过Synchronize过程进行。线程的终止和退出:1)自动退出:一个线程从Execute()过程中退出,即意味着线程的终止,此时将调用Windows的ExitThread()函数

5、来清除线程所占用的堆栈。如果线程对象的FreeOnTerminate属性设为True,则线程对象将自动删除,并释放线程所占用的资源。这是消除线程对象最简单的办法。2)受控退出:利用线程对象的Terminate属性,可以由进程或者由其他线程控制线程的退出。只需要简单的调用该线程的Terminate方法,并设置线程对象的Terminate属性为True。一般来说,在线程中,应该不断监视Terminate的值,一旦发现为True,则退出,一般来说,例如在Execute()过程中可以这样写:While not Terminate dobegin.end;3)退出的API函数:关于线程退出的API函数声

6、明如下:Function TerminateThread(hThread:Thandle;dwExitCode:DWORD);不过,这个函数会使代码立刻终止,而不管程序中有没有try.finally机制,可能会导致错误,不到万不得已,最好不要使用。4)利用挂起线程的方法(suspend)利用挂起线程的suspend方法,后面跟个Free,也可以释放线程,例如:thread1.suspend; /挂起thread2.free; /释放二、多线程的同步机制同步机制,研究多线程的同步机制的必要性在于,多线程同步工作时,如果同时调用相同的资源,就可能会出现问题,如对全局变量、数据库操作发生冲突,甚至产

7、生死锁和竞争问题。举个发生冲突的实例看一下:一般来说,对内存数据加一的操作分解以后有三个步骤:1、从内存中读出数据2、数据加一3、存入内存现在假设在一个两个线程的应用中用Inc进行加一操作可能出现的一种情况:1、线程A从内存中读出数据(假设为3)2、线程B从内存中读出数据(也是3)3、线程A对数据加一(现在是4)4、线程B对数据加一(现在也是4)5、线程A将数据存入内存(现在内存中的数据是4)6、线程B也将数据存入内存(现在内存中的数据还是4,但两个线程都对它加了一,应该是5才对,所以这里出现了错误的结果)1.临界区(Critical Sections)临界区(CriticalSection)

8、是一项共享数据访问保护的技术。对它只有两个操作:Enter和Leave,这两个操作也是原子操作。它的保护原理是这样的:当一个线程A调用某一个Enter后,开始访问某个数据D,如果此时另一个线程B也要访问数据D,则它会在调用这个Enter时,发现已经有线程进入临界区,然后线程B就会被挂起,等待线程A调用Leave。当线程A完成操作,调用Leave离开后,线程B就会被唤醒,并设置临界区标志,开始操作数据,这样就防止了访问冲突varCS:TRTLCriticalSection;/被声明在程序最上方,作为线程都可以使用的全局变量。initializeCriticalSection(cs); /初始化P

9、rocedure InterlockedIncrement( var aValue : Integer );Begin EnterCriticalSection(CS);/独占 Inc( aValue ); LeaveCriticalSection(CS);/解除独占End;现在再来看前面那个例子:1.线程A进入临界区(假设数据为3)2.线程B进入临界区,因为A已经在临界区中,所以B被挂起3.线程A对数据加一(现在是4)4.线程A离开临界区,唤醒线程B(现在内存中的数据是4)5.线程B被唤醒,对数据加一(现在就是5了)6.线程B离开临界区,现在的数据就是正确的了。临界区就是这样保护共享数据的访

10、问请注意,临界区只能在一个进程内使用,可以在多处设置调用enter。不要长时间锁住一份资源,如果你一直让资源被锁定,你就会阻止其它线程的执行,并把整个程序带到一个完全停止的状态,所以千万不要在一个ciritical section中调用sleep()或任何Wait()函数。ciritical section的一个缺点是,它不是核心对象,如果进入ciritical section的那个线程结束了或者当掉了,而没有调用LeaveCriticalSection的话,系统没有办法将该ciritical section清除,如果你需要这样的机能,你应该使用mutex。VOID InitializeCri

11、ticalSection(LPCRITICAL_SECTION lpCriticalSection/一个指针,指向欲被初始化的CRITICAL_SECTION变量);函数功能:初始化一个临界对象,当你用毕临界对象时,必须调用DeleteCriticalSection()清除它。VOID DeleteCriticalSection (LPCRITICAL_SECTION lpCriticalSection/临界对象指针);函数功能:申请删除临界对象VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection/临界对象指针);函数功能

12、:申请进入临界对象VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection/临界对象指针);函数功能申请进入临界对象2.互斥器(Mutexes)一个时间内只能够有一个线程拥有mutex,就好像同一个时间只能够有一个线程进入同一临界区。Mutex和critical section还是有差别的:1.锁住一个未被使用的Mutexes,比锁住一个未被使用的critical section,需要花费几乎100倍的时间2. Mutexes可以跨进程使用,critical section则只能够在同一个进程中使用3.等待一个Mutexes时

13、,你可以指定结束等待的时间长度,但对于critical section则不行。两种对象的相关函数比较:CRITICAL_SECTIONMutex核心对象InitializeCriticalSection()CreateMutex()OpenMutex()EnterCriticalSection()WaitForSingleObject()WaitForMultipleObject()MsgWaitForMutipleObjects()LeaveCriticalSection()ReleaseMutex()DeleteCriticalSection()CloseHandle()Mutex的使用机

14、制:1.有一个mutex,此时没有任何线程拥有它,此时它处于非激发状态。2.某个线程调用WaitforSingleObject()或任何其它的wait函数,并指定该mutex的handle为参数3.win32于是将该mutex的拥有权给予这个线程,然后将此mutex设为激发状态,于是wait.函数返回4.wait.函数返回后,win32立刻又将mutex设为非激发状态,是任何处于等待状态下的其它线程没有办法获得其拥有权5.获得该mutex的线程调用Release,将mutex释放掉。于是循环到第一步。如果线程拥有一个mutex,而在结束前没有调用releaseMutex,mutex不会被摧毁,

15、该mutex会被win32视为“未被拥有”以及“未被激发”,下一个等待中的线程会被以WAIT_ABANDONED_0通知。如果是WaitForMultipleObjects()等待辞mutex,函数返回值介于WAIT_ABANDONED_0和WAIT_ABANDONED_0+n之间,n是指handle数组的元素个数。HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);参数lpMutexAttributes:安全属性。Null表示使用默认的属性。bInitialOwner:如果你希望调用这个函数的线程拥有mutex,就将此值设为truelpName:互斥对象的名称返回值如果成功,则返回一

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号