7-3 读者写者饿死问题

半城伤御伤魂 提交于 2020-01-20 04:43:58

参考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);
}

结论:
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!