草庐IT

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

coder 2024-02-07 原文

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

  • 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 并且它选择未锁定的一个并为我锁定它)。

最佳答案

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

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

  • 一个条件变量来表示“站点中有空闲空间”
  • 代表车站可用空间的计数器(或其他方式,例如两个 bool 值)
  • 保护这些的互斥体

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

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

在代码中:

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

关于c++ - 只锁定两个可能的互斥量之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50714317/

有关c++ - 只锁定两个可能的互斥量之一的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  5. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

随机推荐