【发布时间】:2023-03-28 09:25:02
【问题描述】:
这似乎应该是一个众所周知的问题,但我无法找到一个好的解决方案(无论是从我的大脑还是互联网上)。
首先,我们举一个非常简单的例子:
mutex request <-- init to 0
mutex response <-- init to 0
Service thread (Guy S):
while not finished
wait(request)
do stuff
signal(response)
Someone requestion service (Guy U):
signal(request)
wait(response)
do stuff with results
到目前为止一切顺利。 U(用户)向S(服务)发出信号,并等待其响应。一切都很好。
现在想象一下,如果有很多用户请求相同的服务。现在服务的性质是结果随时间变化(更准确地说是周期性变化)。因此,如果 10 个用户同时或多或少地请求该服务,则该服务只能安全地运行一次。
首先想到的是:
Guy S:
while not finished
wait(request)
do stuff
trywait(request)
broadcast(response)
Guy U:
signal(request)
wait(response)
do stuff with results
这里的不同之处在于,首先Strywaits 应请求有效地将其设置为 0,因此如果许多人已发出信号,则只有一个请求会通过。当然,互斥体的上限为 1,因此所有额外的信号累积为 1,这将被 trywait 删除。第二个变化是,S 将 broadcast 响应,因此所有 Us 都将被解锁。
乍一看还不错,但是有问题。想象一下以下的执行顺序:
Guy S: Guy U1: Guy U2:
wait(request)
signal(request)
working
signal(request)
wait(response)
working
trywait(request)
broadcast(response)
wait(response)
working
(loop)
如果你仔细观察,U2 会被阻止,除非有人再次发送请求(天知道将来什么时候)。非常糟糕。
即使只有一个用户,也可能发生这种情况:
Guy S: Guy U:
wait(request)
signal(request)
working
trywait(request)
broadcast(response)
wait(response)
(loop)
谁能想出一个好主意,或者指导我使用一个已知的算法?
附加信息:
-
S仅定期提供新数据,但根据应用程序,用户可能会决定偶尔(通过请求)而不是定期获取数据。如果用户请求太快,我让他等待下一个周期,所以这不是问题。 - 我可以访问读写器锁、条件变量、信号量和互斥锁。 Readers-writer 看起来很有希望获得响应锁,但目前还不清楚所有用户何时都通过了他们的
wait(response)部分。
【问题讨论】:
标签: c synchronization mutex semaphore