的具体内容。 只需要在 lpCriticalSection 中传递未初始 化的记录,InitializeCriticalSection()过程就会填充这个记录。 注意 Microsoft 故意隐瞒了 TRTLCriticalSection 的细节。因为,其内容 在不同的硬件平台上是不同的。在基于 Intel 的平台上,TRTLCriticalSection 包含一个计数器、一个指示当前线程句柄的域和一个
系统事件的句柄。在 Alpha 平台上,计数器被替换为一种 Alpha-CPU 数据结构,称为 spinlock。在记录被 填充后,我们就可以开始创建临界区了。这时我们需要用 EnterCriticalSection()和 LeaveCriticalSection()来封装代码块。这两个过 程的声明如下: procedure EnterCriticalSection(var lpCriticalSection:TRRLCriticalSection);stdcall; procedure LeaveCriticalSection(var lpCriticalSection:TRRLCriticalSection);stdcall; 正如你所想的,参数 lpCriticalSection 就是由 InitializeCriticalSection()填充的记录。 当你不需要 TRTLCriticalSection 记录时,应当调用 DeleteCriticalSection()过程,下面是它的声明: procedure DeleteCriticalSection(var lpCr
iticalSection:TRRLCriticalSection);stdcall; 2. 互斥 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨进程 的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此名字创建现 有互斥对象的附加句柄。 提示临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临界区 在没有线程冲突时,要用 1 0 ~ 1 5 个时间片,而事件对象由于涉及到系统内核 要用 400~600 个时间片。 可以调用函数 CreateMutex ( )来创建一个互斥量。下面是函数的声明: function lpMutexAttributes 参数为一个指向 TSecurityAttributtes 记 录的指针。此参数通常设为 0,表示默认的安全属性。bInitalOwner 参数表示创 建互斥对象的线程是否要成为此互斥对象的拥有者。当此参数为 False 时, 表 示互斥对象没有拥有者。 lpName 参数指定互斥对象的名称。设为 nil 表示无命名,如果参数不是设
为 nil,函数会
搜索是否有同名的互斥对象存在。如果有,函数就会返回同名互 斥对象的句柄。否则,就新创建一个互斥对象并返回其句柄。 当使用完互斥对象时,应当调用 CloseHandle()来关闭它。 在程序中使用 WaitForSingleObject()来防止其他线程进入同步区域的代 码。此函数声明如下:
(**************************************以下尚未整理 *********************************) function 这个函数可以使当前线程在 dwMilliseconds 指定的时间内睡眠,直到 hHandle 参数指定的对象进入发信号状态为止。一个互斥对象不再被 线程拥有时, 它就进入发信号状态。 当一个进程要终止时, 它就进入发信号状态。 dwMilliseconds 参数可以设为 0,这意味着只检查 hHandle 参 数指定的对象是否处于发信号状态,而后立即返回。dwMilliseconds 参数设为 INFINITE,表示如果信号不出现将一直等下去。 这个函数的返回值如下 WaitFor SingleObject()函数使用的返回值 返回值 含义 WAIT_ABANDONED 指定的对象是互斥对象, 并且拥有这个互斥对象的线程在 没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这 种情况下,这个互斥对象归当前线程所有,并把它设为非发信号状态 WAIT_OBJECT_0 指定的对象处于发信号状态 WAIT_TIMEOUT 等待的时间已过,对象仍然是非发信号状态再次声明,当一 个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时 首先调用 WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互 斥对象设为不发信号状态。当线程调用 ReleaseMutex()函数并传 递一个互斥对象的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入 发信号状态。 注意