参考https://blog.csdn.net/booksyhay/article/details/82762278
在之前的解决方案中,会存在一个问题: 作者可能会饿死。
如果写者到达的时候,临界区中有读者,那么当读者来来往往时,它可能会在队列中等待。只要新读者在最后一位读者离开之前到达,房间里总会有至少一位读者。
这种情况不是僵局,因为一些线程正在取得进展,但这并不是完全可取的。只要系统上的负载很低,这样的程序就可以工作,因为这样写者就有很多机会。但随着负载的增加,系统的行为会迅速恶化(至少从写者的角度来看)。
思考:扩展此解决方案,以便在写者到达时,现有读者可以完成,但不能再进入其他读者。
不会饿死的读者:
可以为读者添加一个旋转门,并允许写者锁定它。 写者必须通过相同的旋转门,但是当他们在旋转门内时,他们应该检查roomEmpty信号量。 如果写者卡在旋转门中,它会强迫读者在旋转门处排队。 然后,当最后一个读者离开临界区时,我们保证接下来至少有一个写者可以进入(在任何排队的读者进入之前)。
readSwitch记录房间里有多少读者; 当第一个读者进入时会锁定roomEmpty;并在最后一个读者退出时将其解锁。
turnstile对于读者来说是一个旋转门,对于写者来说是一个互斥体。
osSemaphoreId_t sem_rootEmpty;
sem_rootEmpty = osSemaphoreNew(1, 1, NULL);
osSemaphoreId_t sem_turnstile;
sem_turnstile = osSemaphoreNew(1, 1, NULL);
LightSwitch readSwitch;
init_light(&readSwitch);
readSwitch.Init(&readSwitch);
写者线程:
如果写者到达时,房间里已有读者,它将阻塞在第2行,这意味着旋转门将被锁定。 这将阻止新的读者进入,因为已经有写者在排队了。
while(1)
{
osSemaphoreAcquire(sem_turnstile, osWaitForever);
{
osSemaphoreAcquire(sem_rootEmpty, osWaitForever);
{
critical_writer();
}
}
osSemaphoreRelease(sem_turnstile);
osSemaphoreRelease(sem_rootEmpty);
}
读者线程:
当最后一个读者离开时,它发出roomEmpty信号,解锁等待的写者。写者立即进入它的临界区,因为没有一个等待的读者可以通过旋转门。
当写者退出时,它会发出turnstile信号,它可以解锁等待的线程,这可能是读者或写者。 因此,这个解决方案保证至少有一个写者可以继续,但是当有写者在排队时,读者仍然有可能进入。
while(1)
{
osSemaphoreAcquire(sem_turnstile, osWaitForever);
osSemaphoreRelease(sem_turnstile);
readSwitch.Lock(&readSwitch, sem_rootEmpty);
{
critical_reader();
}
readSwitch.Unlock(&readSwitch, sem_rootEmpty);
}
结论:
来源:CSDN
作者:小C菜鸟
链接:https://blog.csdn.net/C_cai_niao/article/details/104009497