Concurrency 读者-作者-作者优先级问题 问题
在《信号灯小书》一书中,p。71,存在以下问题: 写一个读者-作者问题的解决方案,优先考虑作者。也就是说,一旦写入程序到达,在所有写入程序离开系统之前,不应允许任何读卡器进入 我得出了一个解决方案,但它与书中给出的有点不同 我的解决方案 共享变量:Concurrency 读者-作者-作者优先级问题 问题,concurrency,semaphore,Concurrency,Semaphore,在《信号灯小书》一书中,p。71,存在以下问题: 写一个读者-作者问题的解决方案,优先考虑作者。也就是说,一旦写入程序到达,在所有写入程序离开系统之前,不应允许任何读卡器进入 我得出了一个解决方案,但它与书中给出的有点不同 我的解决方案 共享变量: readSwitch = Lightswitch() writeSwitch = Lightswitch() noWriters = Semaphore(1) noReaders = Semaphore(1) noReaders.wait() no
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
Semaphore(1)
表示初始化为1的信号量,而Lightswitch
在本书中的定义如下:
class Lightswitch:
def __init__(self):
self.counter = 0
self.mutex = Semaphore(1)
def lock(self, semaphore):
self.mutex.wait()
self.counter += 1
if self.counter == 1:
semaphore.wait()
self.mutex.signal()
def unlock(self, semaphore):
self.mutex.wait()
self.counter -= 1
if self.counter == 0:
semaphore.signal()
self.mutex.signal()
读卡器逻辑:
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
编写器逻辑:
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
书的解决方案
共享变量:
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
读卡器逻辑:
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
编写器逻辑:
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
noReaders.signal()
readSwitch.lock(noWriters)
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
writeSwitch.unlock(noReaders)
noWriters.signal()
readSwitch = Lightswitch()
writeSwitch = Lightswitch()
noWriters = Semaphore(1)
noReaders = Semaphore(1)
noReaders.wait()
readSwitch.lock(noWriters)
noReaders.signal()
# critical section for readers
readSwitch.unlock(noWriters)
writeSwitch.lock(noReaders)
noWriters.wait()
# critical section for writers
noWriters.signal()
writeSwitch.unlock(noReaders)
问题
1) 在读卡器逻辑中,在我的解决方案中,noReaders.signal()
紧接着noReaders.wait()
。这里的想法是,noReaders
就像一种旋转栅门,允许读者通过,但一到就被作者锁定
但是,在本书的解决方案中,noReaders.signal()
是在调用readSwitch.lock(noWriters)
之后完成的
我的订购会产生不正确的行为,有什么原因吗
2) 在writer逻辑中,在我的解决方案中,writeSwitch.unlock(noReaders)
位于noWriters.signal()之前。然而,这本书把它们放在了相反的顺序。我的订购会产生不正确的行为,有什么原因吗
编辑:补充问题
我还有一个问题。我可能对这本书的解决方案有些误解。假设发生以下情况:
- 读卡器1获取
noReaders
(noReaders
变为0)
- 读卡器2在
noReaders
中等待(noReaders
变为-1)
- 写入程序1在
noReaders
中等待(noReaders
变为-2)
- 读卡器3在
noReaders
中等待(noReaders
变为-3)
- 读卡器4在
noReaders
中等待(noReaders
变为-4)
- 读取器1获取
noWriters
(noWriters
变为0)
- 读卡器1发出信号
noReaders
(noReaders
变为-3;读卡器2解锁)
- 读卡器2通过
noWriters
lightswitch;信号noReaders
(noReaders
变为-2,
读卡器3(未被阻止)
在上述情况下,似乎更多的读者可以继续到达并进入关键部分,尽管作者正在等待
此外,考虑到读写器正在循环,完成关键部分的读写器可以循环并再次等待noReaders
,即使已经有写写写器在等待
我在这里误解了什么?根据您的解决方案,以下情况是可能的:
- 新的写入程序出现在
writeSwitch.unlock(noReaders)
之后,但在noWriters.signal()之前
- 新写入程序执行
writeSwitch.lock(noReaders)
- 读卡器执行
readSwitch.lock(noWriters)
,即使有编写器也会进入关键部分
这本书的解决方案首先唤醒了等待的作家,然后才唤醒了读者。您的解决方案首先唤醒读卡器,还允许读卡器在readSwitch.lock(noWriters)
处排队,这样即使有写入程序在等待,它们也可以运行。使用您的解决方案,可能出现以下情况:
- 新的写入程序出现在
writeSwitch.unlock(noReaders)
之后,但在noWriters.signal()之前
- 新写入程序执行
writeSwitch.lock(noReaders)
- 读卡器执行
readSwitch.lock(noWriters)
,即使有编写器也会进入关键部分
这本书的解决方案首先唤醒了等待的作家,然后才唤醒了读者。您的解决方案首先唤醒读者,还允许读者在readSwitch.lock(noWriters)
处排队,这样即使有写入程序等待,他们也可以运行。谢谢。我同意,在writer中,我的解决方案中最后两行的顺序应该颠倒:writer应该在解锁noReaders
之前发出信号noWriters
,以便它优先处理等待的writer。然而,我仍然不清楚为什么我的解决方案读取器的前两行顺序错误。我还添加了一个“编辑:附加问题”部分,带有附加疑问。感谢您的耐心。对于您问题的新增内容:请注意,读者处于关键部分,没有noReaders
lock。因此,一旦读卡器进入其关键部分,写卡器就可以对noReaders
执行锁定,从而阻止其他读卡器。诚然,当发生这种情况时,其他读者可以进入,但读者必须遵守规范:一旦一个作者到达,所有的作者都必须被处理。它并不是说一个作者到达就必须被允许。您的读者解决方案,带有锁定/解锁功能,允许读者在readSwitch.lock(noWriters)
处排队。因此,当一位作者完成并发布了《noWriters》(《代码》)时,即使有新的作者,读者也可能会参与进来。现在看来,这一点已经清楚多了。读取器获取noReaders
后,必须先锁定noWriters
,然后再发信号通知noReaders
。否则,读卡器可以执行readSwitch.lock(noWriters)
,并在编写器发出信号noWriters
时进入关键部分,即使还有其他编写器在等待。谢谢。我同意,在writer中,我的解决方案中最后两行的顺序应该颠倒:writer应该在解锁n之前发出信号noWriters