【问题标题】:Exclusive Queue with Semaphore带信号量的独占队列
【发布时间】:2017-04-18 05:32:42
【问题描述】:

这是关于“信号量小书”第 2 版一书中的解决方案。艾伦·B·唐尼 (Allen B. Downey)。我觉得书中“独占队列”的解决方案(第 3.7.4 节)可能不正确。但是,由于这不太可能,我请求您提供反馈。 我在下面提供了充分的背景信息,以便您无需参考本书就可以做出回应,该书在 GNU 版权下在线提供。

顺便说一句,这绝不与任何课程作业有关

问题陈述:

对于交际舞,有许多舞者分为领导者和追随者,随机到达。我们需要强制规定最多有一对可以跳舞,并且这对必须包括一个领导者和一个追随者。 例如,如果许多领导者到达,他们必须等待追随者配对。此时,如果有很多追随者来了,他们仍然不能结伴而行,而是只有一对来跳舞,等待休息。 我们可以使用信号量(除了需要的共享变量和局部变量)来应用同步约束。

信号量被定义为一个实体,它的值可以由 'signal' 以原子方式递增(以单位为单位),或可由 ' 以原子方式(以单位为单位)递减。 wait' 命令,但无法读取其当前值。此外,一个'wait',在递减后,如果结果为负值,则调用线程将被阻塞。另一方面,每个‘信号’,除了递增之外,总是会唤醒(解除阻塞)一个等待(阻塞)的线程(如果有的话)。信号量可以用任何整数值初始化——零、正数或负数。

有了这个,书中的解决方案如下(书中列出了3.18和3.19)。

书中的解决方案:

‘mutex’和队列都是信号量。 “mutext”初始化为“1”,而两个队列都初始化为“0”。共享变量‘leaders’和‘followers’都初始化为‘0’

       Leader                             Follower
       ======                             ========

1      mutex.wait()                       mutex.wait()
2      if followers > 0                   if leaders > 0
3            followers--                        leaders--
4            followerQueue.signal()             leaderQueue.signal()
5      else                               else
6            leaders++                          followers++
7            mutex.signal()                     mutex.signal()
8            leaderQueue.wait()                 followerQueue.wait()
9      end-if                             end-if
10     dance()                            dance()
11     mutex.signal()

我的担忧:

基于上述解决方案,为了强制任何新对在当前对完成之前不继续,当前对中只有一个会在他们的舞蹈(第 10 行)。 但是,我可以想象这样一种情况,它可能违反只有一对跳舞的限制,并且这对必须由每个类别中的一个组成——领导者和追随者。
想象一下,很少有领导首先到达,他们都将在 leaderQueue (第 8 行)等待。此时,一个跟随者,比如 F1,到达。 F1 将获得 mutex 并唤醒一个领导者,比如 L1,然后他们两个都会继续跳舞。 F1 仍然持有 mutex(其当前值设置为“0”)。有趣的是,有点夸张的是,领导者(比如 L1)开始跳舞并结束;甚至在跟随者 F1 仍在准备跳舞时,继续发出信号表明这对已经完成。 mutex 现在是“1”,想象另一个跟随者,比如 F2,到达。 F2 现在将获得 mutex 并将唤醒另一个领导者,例如 L2。 F2 和 L2 都开始跳舞,而 F1 还没有跳完。因此,我们遇到了一种情况,它违反了一次只有一对跳舞的预期约束。

如果我遗漏了什么,请告诉我。

附注我衷心感谢唐尼教授的这本精彩的书

【问题讨论】:

  • 我在阅读解决方案时也想到了您所描述的情况。我会说你是对的,但我没有花太多时间在这个问题上。用程序测试你的假设(让领导者的舞蹈比追随者的舞蹈持续时间短得多)并最终将你的想法邮寄给作者可能是有指导意义的。
  • @Margaret Bloom - 非常感谢。

标签: multithreading concurrency computer-science semaphore


【解决方案1】:

目前领导者和追随者定义如下:

领导:

mutex.wait()
if followers > 0:
    followers--
    followerQueue.signal()
else:
    leaders++
    mutex.signal()
    leaderQueue.wait()

dance()
rendezvous.wait()
mutex.signal()

关注者:

mutex.wait()
if leaders > 0:
    leaders--
    leaderQueue.signal()
else:
    followers++
    mutex.signal()
    followerQueue.wait()

dance()
rendezvous.signal()

集合点现在可以处理您的问题。但是,我认为具有两个互斥锁和一个集合点的解决方案将是一个更好的选择(除非有人可以反驳它)

下面是代码:

领导:

mutex1.lock();
rendezvous.wait();
dance();
mutex1.unlock();

关注者:

mutex2.lock();
rendezvous.wait();
dance();
mutex2.unlock();

为了完整性,rendezvous.wait() 是一个更高阶的语句。实际上,对于追随者,我们会拥有

followerArrived.signal()
leaderArrived.wait()

对于领导者,我们会有

leaderArrived.signal()
followerArrived.wait()

leaderArrived 和 followerArrived 是初始化为 1 的信号孔。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2018-12-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多