只锁定两个可能的互斥量之一

Lock only one of two possible mutexes

我有一个模拟汽车车间的多线程 C++ 程序。基本上 car 在这里是一个线程,station 是一个资源。它是这样工作的:汽车进入一个车间,它有一个站点列表(只是整数),它必须访问,才能得到修理。有 3 种类型的电台:

最后两种类型对我来说很容易,因为在 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 一些功能,它选择未锁定的功能并为我锁定)。

对于您的情况,我会使用 try_lock 方法。此方法 returns true(并锁定互斥量)如果可以锁定,false 否则(已锁定互斥量)。

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

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

不过,这里有一个条件变量,您可以在此处使用它。您将需要:

  • 用于发出信号的条件变量 "there's free space in the station"
  • 一个计数器(或其他方式,例如两个布尔值)表示站点中的空闲 spaces
  • 保护这些的互斥体

进站时,锁上互斥锁,看看有没有空闲space。如果有,占用一个,释放互斥量,并得到修复。如果两者都已满,则等待条件变量(这将释放互斥量)。

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

在代码中:

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();
    }
}