上次跟大家分享了线程的标准代码,其实程的使用中最重要的是线程的同步问题,如果你在使用线程后,发现你的界面经常被卡死,或者无法显示出来,显示混乱,你的使用的变量值老是不按预想的变化,结果往往出乎意料,那么你很有可能是忽略了线程同步的问题。
当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源。例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件中的字符数。当然,在把整个文件调入内存之前,统计它的计数是没有意义的。但是,由于每个操作都有自己的
线程,操作系统会把两个线程当作是互不相干的任务分别执行,这样就可能在没有把整个文
件装入内存时统计字数。为解决此问题,你必须使两个线程同步工作。存在一些线程同步地
址的问题,Windows提供了许多线程同步的方式。在本节您将看到使用临界区、互斥、信
号量、事件、全局原子和Synchronize函数来解决线程同步的问题。
下面的同步技术一般均有两种使用方式,一种是直接使用WindowsAPI函数,一种是使用
由Delphi对API函数进行封装的类。
以下函数以Delphi2009中的函数格式为准。
1.CriticalSections临界区
临界区是一种最直接的线程同步方式。所谓临界区,就是一次只能由一个线程来执行的一段
代码。例如把初始化数组的代码放在临界区内,另一个线程在第一个线程处理完之前是不会
被执行的。临界区非常适合于序列化对一个进程中的数据的访问,因为它们的速度很快。
(1).使用EnterCriticalSection()和LeaveCriticalSection()API函数
在使用临界区之前,必须定义一个TRTLCriticalSection类型的记录变量并使用
InitializeCriticalSection()过程来初始化临界区。该过程多半在窗体创建时或在程序初始化时
执行。
其声明如下:
procedureInitializeCriticalSection(varlpCriticalSection:TRTLCriticalSection);stdcall;
lpCriticalSection参数是一个TRTLCriticalSection类型的记录,并且是变参。至于
TRTLCriticalSection是如何定义的,这并不重要,因为很少需要查看这个记录中的具体内容。
只需要在lpCriticalSection中传递未初始化的记录,InitializeCriticalSection()过程就会填
充这个记录。
注意:Microsoft故意隐瞒了TRTLCriticalSection的细节。因为,其内容在不同的硬件平台
上是不同的。在基于Intel的平台上,TRTLCriticalSection包含一个计数器、一个指示当前
线程句柄的域和一个系统事件的句柄。在Alpha平台上,计数器被替换为一种Alpha-CPU数据结构,称为spinlock。
在记录被填充后,我们就可以开始创建临界区了。createmutex这时我们需要用EnterCriticalSection()和
LeaveCriticalSection()来封装代码块,这两个函数分别代表进入和离开临界区,将要同步的
代码块放在这两个函数中间。在第一个线程调用了EnterCriticalSection()之后,所有别的
线程就不能再进入代码块并挂起等待第一个线程离开临界区。下一个线程要等第一个线程调
用LeaveCriticalSection()后才能被唤醒。这两个过程的声明如下:
procedureEnterCriticalSection(varlpCriticalSection:TRTLCriticalSection);stdcall;//进入临界区
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-32871-1.html
美国从来就不想帮谁
主要是中国的国籍不开放