我不明白在第二个读者 - 作者问题的通用解决方案中读者程序一开始时最外层互斥体的目的是什么。
为了说明这一点,我将从适当的维基百科条目(link)发布一个代码。我在谈论mutex_3:
READER
P(mutex_3);
P(r);
P(mutex_1);
readcount := readcount + 1;
if readcount = 1 then P(w);
V(mutex_1);
V(r);
V(mutex_3);
reading is performed
P(mutex_1);
readcount := readcount - 1;
if readcount = 0 then V(w);
V(mutex_1);
我能想到的唯一答案就是阻止新读者的涌入。但我认为,除了核心功能之外,还有下一个互斥锁即r。我错了吗?
答案 0 :(得分:1)
我看到这个问题有一段时间被问到了,但我想我会发布答案,以防将来帮助其他人。
我们使用互斥锁来保护共享资源不被多个线程同时访问。在mutex_3的情况下,如果你看一下紧跟在P(mutex_3)之后的代码,我们看到我们要保护的共享资源是信号量r。因此,使用mutex_3可以确保只有一个读取器可以在任何时间执行P(r)和V(r)之间的代码段。
要了解为什么这个互斥锁很重要,我们还需要考虑编写器的代码。来自维基百科:
WRITER
P(mutex_2);
writecount := writecount + 1;
if writecount = 1 then **P(r)**; <-- Writer waits on semaphore r
V(mutex_2);
P(w);
writing is performed
V(w);
P(mutex_2);
writecount := writecount - 1;
if writecount = 0 then V(r);
V(mutex_2);
要注意的关键部分是粗体。如您所见,作者和读者都在信号量r上调用P(r)。在这种情况下,不清楚谁的呼叫首先成功。我们假设编写者在调用P(r)时没有得到任何优先权(如果确实如此,则不需要mutex_3)。
但是,第二个读者 - 写作者问题的问题陈述表明作者应该尽快开始。如果按照先来先服务的方式进行调度,那么在上述情况下,如果读者设法首先调用P(r),则读者的呼叫成功。然后作者被推迟,我们不想要。
因此,解决方案是在读卡器的设置代码周围放置一个互斥锁(mutex_3)。现在,当读者调用V(r)时,不能有任何其他读者等待r,因为其他读者需要获取mutex_3才能调用P(r),但当前读者持有mutex_3!然而,有一个作家在等待r,所以在这种情况下,作者对P(r)的调用总是尽快成功,因为它是唯一一个等待r的人。