Как можно попытаться получить мьютекс-подобную блокировку в go, либо немедленно прервав (как это делает TryLock в других реализациях), либо соблюдая некоторую форму крайнего срока (в основном LockBefore )?
Я могу вспомнить две ситуации прямо сейчас, где это было бы очень полезно и где я ищу какое-то решение.Первый из них: сервис с высокой нагрузкой на процессор, который получает запросы, чувствительные к задержке (например, веб-сервис)В этом случае вы захотите сделать что-то вроде примера RPCService ниже.Можно реализовать его как рабочую очередь (с каналами и прочим), но в этом случае становится все труднее измерить и использовать весь доступный ЦП.Также можно просто согласиться с тем, что к тому времени, когда вы получите блокировку, ваш код может быть уже истекшим сроком, но это не идеально, так как тратит некоторое количество ресурсов и означает, что мы не можем делать что-то вроде «деградированного ad-hoc».response ".
/* 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, если я хочу решить их?Мне известно о выпуске 6123 , который, по-видимому, говорит о том, что такого не существует, и то, что я подхожу к этим проблемам, совершенно непросто.