如何在 go 中只尝试获取类似互斥锁的锁,要么立即中止(就像TryLock在其他实现中所做的那样),要么通过观察某种形式的截止日期(基本上是LockBefore)?
我现在可以想到两种情况,这会非常有帮助,而我正在寻找某种解决方案。第一个是:接收延迟敏感请求的 CPU 密集型服务(例如 Web 服务)。在这种情况下,您可能希望执行类似于下面的RPCService示例的操作。可以将其实现为工作队列(带有通道和其他东西),但在那种情况下,衡量和利用所有可用 CPU 变得更加困难。也可以只接受当你获得锁时你的代码可能已经超过了截止日期,但这并不理想,因为它浪费了一些资源并且意味着我们不能做像“降级的临时任务”这样的事情回复”。
/* Example 1: LockBefore() for latency sensitive code. */
func (s *RPCService) DoTheThing(ctx context.Context, ...) ... {
if s.someObj[req.Parameter].mtx.LockBefore(ctx.Deadline()) {
defer s.someObj[req.Parameter].mtx.Unlock()
... expensive computation based on internal state ...
} else {
return s.cheapCachedResponse[req.Parameter]
}
}
另一种情况是当你有一堆应该被触摸的对象,但它们可能被锁定,并且触摸它们应该在一定时间内完成(例如更新一些统计数据)。在这种情况下,您还可以使用LockBefore()或某种形式的TryLock(),请参阅下面的统计信息示例。
/* Example 2: TryLock() for updating stats. */
func (s *StatsObject) updateObjStats(key, value interface{}) {
if s.someObj[key].TryLock() {
defer s.someObj[key].Unlock()
... update stats ...
... fill in s.cheapCachedResponse ...
}
}
func (s *StatsObject) UpdateStats() {
s.someObj.Range(s.updateObjStats)
}
为了便于使用,我们假设在上述情况下我们谈论的是相同的s.someObj。任何对象都可能被DoTheThing()操作阻塞很长时间,这意味着我们希望在updateObjStats中跳过它。此外,我们希望确保在DoTheThing()中返回廉价响应,以防我们无法及时获得锁定。
不幸的是, sync.Mutex 仅具有功能Lock()和Unlock()。没有办法潜在地获取锁。有没有一些简单的方法可以做到这一点?我是不是从一个完全错误的角度来处理这类问题,是否有一种不同的、更“走”的方式来解决它们?或者如果我想解决这些问题,我是否必须实现自己的 Mutex 库?我知道issue 6123似乎暗示没有这样的事情,而且我处理这些问题的方式完全不可行。
明月笑刀无情
BIG阳
慕雪6442864
Helenr
相关分类