仅锁定两个可能的互斥锁中的一个

时间:2018-06-06 07:14:57

标签: c++ multithreading mutex

我有一个模拟汽车研讨会的多线程C ++程序。基本上car是一个线程,station是一个资源。它的工作方式如下:汽车进入车间,它有一个车站列表(只是整数),它必须访问,以便修复。有三种类型的站:

  • 1x2站 - 1站可同时修理2辆车
  • 1x1站 - 1站可以一次修理1辆车
  • 2x1站 - 完成工作需要2个站点

最后两种类型对我来说很容易,因为在1x1类型中我只需要锁定station上的互斥锁,其他线程必须等待。在2x1类型上,我只是在两个站点上std::lock,以避免死锁等。

问题在于第一种类型。让我们想象一下,修理两辆车意味着一辆车在车站的左侧,另一辆在右侧(我将不得不用ncurses绘制这种情况)。所以我考虑为这样的1x2类型实现一个站点:

class station1x2 {
public:
    std::mutex r_mutex;
    std::mutex l_mutex;
}

所以我想锁定r_mutexl_mutex,因此有4种可能的情况:

  • 他们两个都没有锁定,我锁定其中任何一个
  • 右边一个锁定,我锁定左边一个
  • 左边一个被锁定,我锁定右边
  • 他们两个都被锁定了,我等了

这里的问题是:C ++中是否存在锁定给定互斥锁之一的机制? (就像我给了一些函数我的r_mutex和l_mutex它选择了未锁定的函数并为我锁定它。)

2 个答案:

答案 0 :(得分:11)

此处互斥锁不是正确的同步原语。这可以通过信号量(基本上是0-n原语,其中互斥锁为0-1)来完成,但标准库中没有信号量。

但是,您可以在此处使用条件变量。你需要:

  • 一个条件变量,表示“站内有可用空间”
  • 代表车站自由空间的柜台(或其他方式,例如两个布尔)
  • 保护这些
  • 的互斥锁

进入电台时,锁定互斥锁并查看是否有空闲空间。如果有,占用一个,释放互斥锁,并进行修复。如果两者都已满,请等待条件变量(这将释放互斥锁)。

完成修复后,锁定互斥锁,将空间标记为空闲,释放互斥锁并通知条件变量(因为现在有空闲空间)。

在代码中:

class station1x2 {
public:
    std::mutex mutex;
    std::condition_variable cond;
    int freeSpaces;

    void enter() {
      std::unique_lock<std::mutex> l(mutex);
      cond.wait(l, [&]() { return freeSpaces > 0; }
      --freeSpaces;
    }

    void exit() {
      {
        std::unique_lock<std::mutex> l(mutex);
        ++freeSpaces;
      }
      cond.notify_one();
    }
}

答案 1 :(得分:2)

在您的情况下,我会使用try_lock方法。如果可以锁定,此方法返回true(并锁定互斥锁),否则false(已锁定互斥锁)。

if (!r_mutex.try_lock() && !l_mutex.try_lock())
  std::cout << "All mutexes already locked" << std::endl;
相关问题