【问题标题】:C++ partial mutex/critical section lockC++ 部分互斥锁/临界区锁
【发布时间】:2012-10-16 06:53:17
【问题描述】:

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

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

该应用程序是多线程的,所以我正在考虑使用 mutex/events/critical 部分来处理这个问题。

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

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

提前致谢, 马丁

【问题讨论】:

  • 您是否还希望保护并发 setter 免受相同属性的影响(如果没有,为什么不)?
  • 所有属性都是完全独立的,因此可以安全地同时更改它们。一个正常的临界区可以解决我的问题;但是,如果二传手可以互相阻止,我担心这会给我带来很大的开销。 setter 被非常频繁地调用,并且 Update 方法被调用时之间的时间间隔最小(意味着不那么频繁)。
  • 我的问题不是 setPropertyX 是否独立于 setPropertyY。这是您是否需要防范并发 setPropertyX 调用。如果这不是问题,请参阅下面的答案。 (老实说,我很困惑它怎么成为一个问题,但你比我更了解代码)。

标签: c++ events mutex critical-section


【解决方案1】:

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

在任何给定的设置器中:

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

在主更新例程中

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

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

说了这么多,还是单独考虑属性并发。

【讨论】:

  • 谢谢 - 很抱歉误解了你的问题 - 不,我不需要防范并发 setPropertyX 调用 - 所以你的建议将解决我的问题 - 谢谢
  • 存在饥饿威胁,如果 setter 调用非常频繁,则需要调用 Update 方法。
  • @Martin 你的意思是一个暴击秒或(n)暴击秒,每个属性一个?前者肯定会起作用,但属性集将变得同步。后者将起作用,需要一连串的 crit-sec 等待(每个属性一个)。几乎有很多方法可以做到这一点。
  • 您需要确保 Update 方法不访问设置器,否则它们会阻塞。
【解决方案2】:

您可以为每个属性设置一个临界区。在 setter 中,您获取特定于属性的临界区并完成您的工作,这样每个属性就不会相互阻塞。

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

【讨论】:

  • 谢谢 - 是的,这可以解决问题 - ii 如果关键部分需要很多:) - 但我仍然会考虑一个解决方案 - 谢谢
【解决方案3】:

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

在每个设置器中:

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

在主更新例程中:

  • 获取临界区 csUpdate
  • while (InterlockedCompareExchange(&countSettersActive, 0, 0) != 0) { sleep(1); }
  • 进行更新
  • 发布临界区 csUpdate

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2015-10-08
    • 2013-08-07
    • 2016-10-25
    • 2021-04-16
    • 2017-09-30
    • 2022-07-31
    相关资源
    最近更新 更多