同步数据结构
并发运行时提供了几种数据结构,用于同步对来自多个线程的共享数据的访问。 当你有不经常修改的共享数据时,这些数据结构很有用。 一个同步对象,例如,一个关键部分,会导致其他线程等待,直到共享资源可用。 因此,如果使用这样的对象来同步对经常使用的数据的访问,会失去应用程序的可扩展性。 并行模式库 (PPL) 提供了 concurrency::combinable 类,使你能够在无需同步的情况下在几个线程或任务之间共享资源。 有关 combinable
类的详细信息,请参阅并行容器和对象。
章节
本主题详细介绍了以下异步消息块类型:
critical_section
concurrency::critical_section 类表示一个协作性互相排斥对象,该对象将会让位于其他任务,而不是优先于它们。 当多个线程需要对共享数据的独占读取和写入访问权限时,关键部分非常有用。
critical_section
类是非重入的。 如果已拥有锁的线程调用 concurrency::critical_section::lock 方法,该方法将引发类型为 concurrency::improper_lock 的异常。
方法和功能
下表显示了 critical_section
类定义的重要方法。
方法 | 说明 |
---|---|
lock | 获取关键部分。 调用上下文在获取锁之前一直处于阻止状态。 |
try_lock | 尝试获取关键部分,但不阻止。 |
unlock | 释放关键部分。 |
[返回页首]
reader_writer_lock
concurrency::reader_writer_lock 类提供对共享数据的线程安全的读/写操作。 当多个线程需要对共享资源进行并发读取访问,但很少对该共享资源进行写入时,可以使用读取器/编写器锁。 在任何时候,此类都只允许一个线程对一个对象进行写入访问。
reader_writer_lock
类的性能优于 critical_section
类,因为 critical_section
对象获取对共享资源的独占访问权限,从而阻止并发读取访问。
与 critical_section
类一样,reader_writer_lock
类表示一个协作性互相排斥对象,该对象将会让位于其他任务,而不是优先于它们。
当必须写入共享资源的线程获取读取器/编写器锁时,同样必须访问该资源的其他线程一直处于被阻止状态,直到编写器释放锁。 reader_writer_lock
类是一个写优先锁的示例,该锁用于在取消阻止等待读取器之前,先取消阻止等待编写器。
与 critical_section
类一样,reader_writer_lock
类是非重入的。 如果已拥有锁的线程调用 concurrency::reader_writer_lock::lock 和 concurrency::reader_writer_lock::lock_read 方法,它们将引发类型为 improper_lock
的异常。
注意
由于 reader_writer_lock
类是非重入的,因此无法将只读锁升级为读取器/编写器锁或将读取器/编写器锁降级为只读锁。 执行这两种操作都会产生不明确的行为。
方法和功能
下表显示了 reader_writer_lock
类定义的重要方法。
方法 | 说明 |
---|---|
lock | 获取对锁的读/写访问权限。 |
try_lock | 尝试获取对锁的读/写访问权限,但不阻止。 |
lock_read | 获取对锁的只读访问权限。 |
try_lock_read | 尝试获取对锁的只读访问权限,但不阻止。 |
unlock | 释放锁。 |
[返回页首]
scoped_lock and scoped_lock_read
critical_section
和 reader_writer_lock
类提供嵌套帮助程序类,可以简化使用互相排斥对象的方式。 这些帮助程序类称为“作用域锁”。
critical_section
类包含 concurrency::critical_section::scoped_lock 类。 构造函数获取对所提供的 critical_section
对象的访问权限;析构函数释放对该对象的访问权限。 reader_writer_lock
类包含 concurrency::reader_writer_lock::scoped_lock 类,后者与 critical_section::scoped_lock
相似,只不过它管理对提供的 reader_writer_lock
对象的写入访问权限。 reader_writer_lock
类还包含 concurrency::reader_writer_lock::scoped_lock_read 类。 此类管理对所提供的 reader_writer_lock
对象的读取访问权限。
手动处理 critical_section
和 reader_writer_lock
对象时,作用域锁提供了几个优势。 通常,在堆栈上分配作用域锁。 作用域锁在被销毁时会自动释放对其互相排斥对象的访问权限;因此,你不需要手动解锁基础对象。 当函数包含多个 return
语句时,这非常有用。 作用域锁还可以帮助你编写异常安全代码。 当 throw
语句导致堆栈展开时,将调用任何活动作用域锁的析构函数,因此会始终正确地释放互相排斥对象。
注意
使用 critical_section::scoped_lock
、reader_writer_lock::scoped_lock
和 reader_writer_lock::scoped_lock_read
类时,不要手动释放对基础互相排斥对象的访问权限。 这会将运行时置于无效状态。
event
concurrency::event 类表示一个同步对象,此对象的状态可以是信号通知的,也可以是非信号通知的。 与同步对象(如关键部分)不同,其用途是保护对共享数据的访问,事件会同步执行流。
当一个任务完成另一个任务的工作时,event
类非常有用。 例如,一个任务可能会向另一个任务发出信号,告知它已从网络连接或文件中读取数据。
方法和功能
下表显示了 event
类定义的几个重要方法。
方法 | 说明 |
---|---|
wait | 等待事件变为发出信号状态。 |
set | 将事件设置为信号通知状态。 |
reset | 将事件设置为非信号通知状态。 |
wait_for_multiple | 等待多个事件变为信号通知状态。 |
示例
有关演示如何使用 event
类的示例,请参阅将同步数据结构与 Windows API 进行比较。
[返回页首]
相关章节
将同步数据结构与 Windows API 进行比较
将同步数据结构的行为与 Windows API 所提供的结构进行比较。
并发运行时
描述可以简化并发编程并包含相关主题链接的并发运行时。