7-3 读者写者饿死问题

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

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

发布了33 篇原创文章 · 获赞 1 · 访问量 340
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览