windows C++ 并行编程-同步数据结构

并发运行时提供了几种数据结构,用于同步对来自多个线程的共享数据的访问。 当你有不经常修改的共享数据时,这些数据结构很有用。 一个同步对象,例如,一个关键部分,会导致其他线程等待,直到共享资源可用。 因此,如果使用这样的对象来同步对经常使用的数据的访问,会失去应用程序的可扩展性。 并行模式库 (PPL) 提供了 concurrency::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    :等待多个事件变为信号通知状态;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值