2024年3月20日发(作者:)

Visual C++线程同步技术剖析:临界区,时间,信号量,互斥量

摘要: 多线程同步技术是计算机软件开发的重要技术,本文对多线程的各种

同步技术的原理和实现进行了初步探讨。

关键词: VC++6.0; 线程同步;临界区;事件;互斥;信号量;

正文

使线程同步

在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立

的操作。更多的情况是一些线程进行某些处理操作,而其他的线程必须对其处理

结果进行了解。正常情况下对这种处理结果的了解应当在其处理任务完成后进

行。

如果不采取适当的措施,其他线程往往会在线程处理任务结束前就去访问处

理结果,这就很有可能得到有关处理结果的错误了解。例如,多个线程同时访问

同一个全局变量,如果都是读取操作,则不会出现问题。如果一个线程负责改变

此变量的值,而其他线程负责同时读取变量内容,则不能保证读取到的数据是经

过写线程修改后的。

为了确保读线程读取到的是经过修改的变量,就必须在向变量写入数据时禁

止其他线程对其的任何访问,直至赋值过程结束后再解除对其他线程的访问限

制。象这种保证线程能了解其他线程任务处理结束后的处理结果而采取的保护措

施即为线程同步。

线程同步是一个非常大的话题,包括方方面面的内容。从大的方面讲,线程

的同步可分用户模式的线程同步和内核对象的线程同步两大类。用户模式中线程

的同步方法主要有原子访问和临界区等方法。其特点是同步速度特别快,适合于

对线程运行速度有严格要求的场合。

内核对象的线程同步则主要由事件、等待定时器、信号量以及信号灯等内核

对象构成。由于这种同步机制使用了内核对象,使用时必须将线程从用户模式切

换到内核模式,而这种转换一般要耗费近千个CPU周期,因此同步速度较慢,

但在适用性上却要远优于用户模式的线程同步方式。

临界区

临界区(Critical Section)是一段独占对某些共享资源访问的代码,在任意

时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界

区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一

直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,

并以此达到用原子方式操作共享资源的目的。

临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用

EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。

所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的

初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码

都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然

有被破坏的可能。

图1 使用临界区保持线程同步

下面通过一段代码展示了临界区在保护多线程访问的共享资源中的作用。通

过两个线程来分别对全局变量g_cArray[10]进行写入操作,用临界区结构对象

g_cs来保持线程的同步,并在开启线程前对其进行初始化。为了使实验效果更加

明显,体现出临界区的作用,在线程函数对共享资源g_cArray[10]的写入时,以

Sleep()函数延迟1毫秒,使其他线程同其抢占CPU的可能性增大。如果不使