这似乎应该是一个众所周知的问题,但我无法找到一个好的解决方案(无论是从我的大脑还是互联网上)。
首先,我们举一个非常简单的例子:
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
这里的不同之处在于,first S
trywait
s on request 有效地将其设置为 0,因此如果很多人已经发出信号,则只有一个请求会通过。当然,互斥体的上限为 1,因此所有额外的信号累积为 1,这将被trywait
. 第二个变化是,响应是否会解除所有S
s的阻塞。broadcast
U
乍一看还不错,但是有问题。想象以下执行顺序:
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)
部分。