3

我在 VS2010 中使用 C++,我有一个带有一堆属性(getter 和 setter)的容器类(实际上是一堆具有属性的对象——但让我们简化它并假设它只是容器类上的一个属性。

在这个容器类上有一个 Update 函数,重要的是在 Update 方法执行时阻塞 setter 方法。

该应用程序是多线程的,所以我想使用互斥锁/事件/关键部分来处理这个问题。

我的问题是:如何在 Update 方法运行时锁定/阻止 setter,而不让 setter 方法相互阻止?此外,我还需要设置器来阻止 Update 方法。

换句话说,我需要一个正常的临界区机制,除了 setter 不应该互相阻塞。

在此先感谢,马丁

4

3 回答 3

3

如果不需要同时保护设置器(例如:setPropertyX(value)),则可以使用单个信号量和手动可重置事件来实现,其中初始资源计数是您要防范的属性数量。

在任何给定的设置器中:

  • 等待设置的 NoUpdatePendingEvent。
  • 获取信号量资源 (1)
  • 更新属性值
  • 释放信号量资源(一)

在主更新例程中

  • NoUpdatePending 事件清除
  • 获取信号量资源 (n)
  • 做更新
  • 释放信号量资源 (n)
  • NoUpdatePending 事件集

其中 (n) 是您拥有的属性的数量。NoUpdatePending 的初始状态已设置,等待它不会重置它(因此只有手动重置要求)。只要有任何属性正在更新,您就无法输入更新。一旦您输入更新代码并清除 NoUpdatePending 事件,传入的 prop-updates 将停止该事件并且不会消耗信号量资源。所有正在运行的 prop-sets 最终都会释放更新继续所需的资源。

综上所述,仍然单独考虑属性并发性。

于 2012-10-16T07:08:21.710 回答
2

您可以为每个属性设置一个关键部分。在设置器中,您获取特定于属性的关键部分并完成您的工作,这样每个属性就不会相互阻塞。

在进行更新之前,在该Update方法中获取所有特定于属性的关键部分。如果有人在您更新时调用它们,这将导致设置器现在阻止。

于 2012-10-16T07:00:17.213 回答
0

这是一个仅使用临界区和整数的选项,并不关心您有多少个 setter:

在每个二传手:

  • 获取临界区 csUpdate
  • InterlockedIncrement(&countSettersActive)
  • 发布临界区 csUpdate
  • 更新属性
  • InterlockedDecrement(&countSettersActive)

在主更新例程中:

  • 获取临界区 csUpdate
  • while (InterlockedCompareExchange(&countSettersActive, 0, 0) != 0) { sleep(1); }
  • 做更新
  • 发布临界区 csUpdate
于 2014-12-11T20:53:30.110 回答