Critical Section Objects
关于互斥段
Critical Section Objects(临界区对象)提供一种同步机制,类似于mutex object(互斥对象),但是Critical Section Objects只能在单进程中使用,无法跨进程共享。
事件、互斥量、信号量都可以被使用在单进程的应用中,但是,Critical Section Objects提供轻量级的、更快、更有效的机制来同步并发执行。
与互斥量类似的是,一个Critical Section在同一时间内仅能被一个线程所拥有,这对于保护共享资源不被并发访问非常有用。 与互斥量不同的是,无法判断该临界区是否被弃用。
从win2003开始,线程不再是通过先来先服务获得临界区。对于大多数代码来说,它显著提高了性能。但是对于一些依赖于先进先出的应用程序来说,执行效率显著降低(例如,应用程序使用临界区作为限速器)。
为了确保你的代码继续正确运行,你需要去增加同步化的层次。
例如,假设你有一个生产者线程和一个消费者线程,它们正在使用Critical Section Objects使它们的工作同步。创建两个Event Objects(事件),每个线程使用信号来表示它已经准备好继续进行另一个线程。消费者线程在进入临界区之前会等待生产者对事件发出信号,并且生产者线程在进入临界区前会等待消费者线程对事件发出信号。在每个线程离开临界区段之后,它会向它的事件发出信号,去释放另一个线程。
win2003和winXP:线程在等待临界区的时候会被加入一个等待队列。它们被唤醒,并且是按照被添加到队列的顺序获得临界区。然而,如果用一个足够快的速度将线程添加到等待队列中,由于唤醒每个等待的线程需要时间,所以性能可能会降低。
进程负责分配临界区所需要的内存。通常,这是通过简单声明一个临界区类型的变量。在进程的线程可以使用它之前,通过使用 InitializeCriticalSection和 InitializeCriticalSectionAndSpinCount这两个方法初始化临界区。
一个线程使用 EnterCriticalSection 和 TryEnterCriticalSection 去请求临界区的所有权。它使用 LeaveCriticalSection 去释放它对临界区的所有权。如果临界区目前被另一线程所拥有, EnterCriticalSection 无限期的等待所有权。相反的,当互斥对象被用于互斥时,等待方法中存在一个超时时间。 TryEnterCriticalSection 尝试在不阻塞调用线程的情况下进入临界区。
当一个线程拥有临界区,它可以无需阻塞就额外调用 EnterCriticalSection 和TryEnterCriticalSection。这防止线程在等待临界区的时候发生死锁。为了释放所有权,线程必须每次进入临界区后调用 LeaveCriticalSection 一次。并不能保证等待的线程获得临界区所有权的先后。
一个线程使用 InitializeCriticalSectionAndSpinCount 和SetCriticalSectionSpinCount 指定临界区的循环次数。循环意味着当线程尝试去获取临界区但是临界区被锁住时,那么该线程进入循环,检查临界区的锁是否释放,如果没有释放,线程进入休眠状态。 在单处理器系统里,循环锁被忽视,并且临界区的循环锁被置为0.在多处理系统里,如果临界区不可用,在信号量上执行等待操作之前,调用线程的循环次数与临界区有关。如果临界区在循环时处于空闲状态,那么调用的线程就不会进入等待状态。
任何进程间的线程可以使用 DeleteCriticalSection 去释放在临界区初始化分配时的系统资源。在方法调用之后,临界区不能用于同步。
当临界区已经被使用,只有在调用EnterCriticalSection的线程,该线程等待该临界区的所有权,会被影响。不等待的线程可以继续运行。
Last updated