首页 / 软件开发 / VC.NET / 并发操作Windows Vista新增的同步原语
并发操作Windows Vista新增的同步原语2010-05-29 MSDN / Robert Saccone本文讨论:条件变量Slim 读取器锁/写入器锁一次性初始化仔细查过锁定本文使用了以下技术:Windows Vista, C++目录条件变量Slim 读取器锁/写入器锁一次性初始化结束语Windows Vista 附带了一系列面向开发人员的令人振奋的新技术,包括 Windows® Presentation Foundation、Windows Communication Foundation 和 Windows Workflow Foundation。事实上,Windows Vista™ 已引入太多新的 .NET 友好技术,因此我们很容易忽略本机 C/C++ 开发人员可用于其应用程序的所有新特性和功能。在本文中,我们将讨论影响本机 C/C++ 开发人员的一些 Windows Vista 新功能。我们将重点介绍新操作系统中引入的几种新线程同步功能:条件变量、Slim 读取器锁/写入器锁和一次性初始化。条件变量条件变量在其他线程库中已经存在一段时间了,只是很遗憾地被 Windows SDK 遗漏了。条件变量主要用来根据一些条件测试的结果同步化一组线程。尽管可通过使用现有同步结构组合来做到这一点,但是条件变量具有释放已获取的锁,并通过一个原子操作进入休眠状态的能力。它还提供了一种更清楚且又少出错的方法,以用于实现所需的行为。Windows SDK for Windows Vista(可供下载)公开了 CONDITION_VARIABLE 结构的条件变量。您可用 InitializeConditionVariable 函数创建该结构。没有用来清理或销毁 CONDITION_VARIABLE 结构的函数,因为底层实现用不着它。通过使用函数 SleepConditionVariableCS(使用关键节时)或 SleepConditionVariableSRW(使用 Slim 读取器锁/写入器锁时),您可让线程等待条件变量。当另一条线程调用 WakeConditionVariable 或 WakeAllConditionVariable 时,这些休眠线程将被释放,这取决于调用线程是想要释放等待条件变量的一条线程还是所有线程。常见的生产者/使用者问题代表了可使用条件变量的情况。这一典型示例是指生产者生成数据并将其置入缓冲区,而使用者则从缓冲区抓取待处理的数据片段的情形。该问题指出了一种需求,即保证生产者不会试图向填满的缓冲区添加数据,而使用者不会试图从空缓冲区抓取数据。我们将分析本情形,以向您说明条件变量是如何帮助解决问题的。针对此例,我们将创建一个向共享队列传送数值数据的单一生产者线程。我们然后创建五个使用者线程。每个使用者线程将从队列中转移一个项目并进行处理。当处理完当前数据段后,使用者线程将循环,无限重复该过程。在早期版本的 Windows 中,可用 Win32 事件和关键节组合来解决生产者/使用者问题。当资源可供使用者使用时,关键节会保护共享资源、避免出现并发性访问和事件信号。在我们首次尝试解决这个问题时,我们将标准模板库 (Standard Template Library, STL) 整数列表用作共享资源。由于列表会动态扩展,我们无需使用事件以信号形式通知列表何时是未填满的,我们只需了解它何时不是空的,这样使用者就能知道其中有内容可供使用。(如果您打算使用固定大小的数组来容纳共享队列,则需要一个未满事件,以确保您不会向缓冲区写入过多内容。)我们随后声明并初始化 CRITICAL_SECTION 对象以及用于说明列表何时不为空的自动重置事件。图 1 所示的生产者线程将首先尝试获取关键节,并且如果获取成功,将随后在共享列表的末尾插入一个整数值。该线程然后释放关键节并设置非空事件。因为我们在使用一个自动重置事件,因此只释放一个等待本事件的线程。 图 1 所示的使用者线程将查看队列是否为空。如果队列不为空,该线程将转移一个项目并释放关键节。如果队列为空,使用者线程将返回休眠状态,继续等待非空事件。在第一个使用者线程忙于处理它从队列转移的项目时,生产者将唤醒另一个使用者线程拾取下一段工作以确保队列处于移动状态。