如何用两组功能进行互斥?

时间:2015-07-29 06:13:46

标签: c++ c multithreading synchronization

我并不是直接询问有关互斥锁的内容,尽管有些相关。

有两组函数A和B.当A中的函数运行时,B中的任何函数都不应该运行,反之亦然。

有多个线程可以调用A或B中的函数,并且应满足上述要求。

我可以通过混合一些锁定方式来想办法来做到这一点,但我很担心最好的方法是什么,或者至少是一些缩小范围的好方法。

3 个答案:

答案 0 :(得分:4)

好的,所以有三种有效状态:

没有任何线程在任何一组中运行函数。

一个或多个线程正在A组中运行功能。

一个或多个线程在B组中运行。

与大多数复杂的锁定方案一样,这可以通过锁内的状态来管理。状态可以是枚举,例如(EgsFree,EgsAonly,EgsBonly),threadCount int,用于跟踪受保护函数中任一组的线程数以及同步对象的容器(不允许运行的线程)等待。

函数需要通过在进入时调用锁定状态(用参数标识其组)和退出来进行协作。

在尝试输入时发现它们不允许运行其功能的线程必须通过引发事件/信号量,将其存储在容器中并在退出锁定状态后等待它来阻止自己。这允许线程将计数递减为0(并因此将状态再次设置为Efree),在退出时迭代容器并使所有等待的线程都准备就绪。

鉴于此框架,您可以根据需要实施反饥饿算法或其他管理方案。

锁中的状态数据很混乱,我希望看到一个更简单的解决方案。 OTOH,它仍然是复杂资源管理的唯一安全方式,我知道这可以依赖于工作并且没有隐藏的种族/死锁潜力。如果你必须对锁定方案过于考虑,那么它可能会在某些时候搞砸了:)

答案 1 :(得分:3)

在我看到Martin James的回答之前,我正在编写这段代码。事实证明,这是未经测试的c ++ 11代码,可以说明他的答案,所以请大声回答。

我认为带引用计数的三向开关可能有效(未经测试的类)

struct ThreeWaySwitch
{
  std::mutex mtx;
  std::condition_variable cv;
  enum State { IDLE, A, B } state;
  int count;

  ThreeWaySwitch() : state(IDLE), count(0) {}
  void switchA() 
  { 
    std::unique_lock l(mtx); 
    while (state == B) cv.wait(l); 
    state = A; 
    ++count; 
  }
  void switchB() 
  { 
    std::unique_lock l(mtx); 
    while (state == A) cv.wait(l); 
    state = B; 
    ++count; 
  }
  void switchIdle() 
  { 
    {
      std::unique_lock(mtx); 
      if (count == 0) return;  // already idle
      if (--count != 0) return; // not idle yet
      state = IDLE;
    }
    cv.notify_all(); 
  }
};

因此每个A函数在entry上调用switchA(),在exit上调用switchIdle(),为B函数调用switchB()。

答案 2 :(得分:0)

我试图找到问题的更开放/简单的答案,你可以这样做:

class A
{
public:
    static void foo1();
    static void foo2();
private:
    static std::shared_ptr<MyMutexClass> m_mmc;
};

class B
{
public:
    static void foo3();
    static void foo4();
private:
    static std::shared_ptr<MyMutexClass> m_mmc;
};

在你的foo功能中,使用组提供的静态互斥锁来保护。 您只需要找到一种方法来正确初始化A :: m_mmc和B :: m_mmc。