2020-03-14 12:11:46 +00:00
|
|
|
|
# keylock
|
|
|
|
|
|
|
|
|
|
Напишите примитив синхронизации, позволяющий "лочить" строки из множества.
|
|
|
|
|
|
2023-03-27 15:27:25 +00:00
|
|
|
|
В обычном `sync.Mutex` лок всего один. В один момент времени этот лок может находиться
|
|
|
|
|
у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем
|
|
|
|
|
ключём - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу
|
2023-03-28 08:44:18 +00:00
|
|
|
|
все локи из этого списка. (Наша аналогия с `sync.Mutex` вовсе не значит, что нужно использовать
|
|
|
|
|
`sync.Mutex` в реализации. Лучше использовать каналы, чтобы проще было реализовать отмену.)
|
2023-03-27 15:27:25 +00:00
|
|
|
|
|
|
|
|
|
В итоге, внутри критической секции может быть сколько угодно горутин, но у всех них множества
|
|
|
|
|
ключей попарно не пересекаются.
|
|
|
|
|
|
|
|
|
|
Например, если к нам придёт 3 горутины:
|
|
|
|
|
|
|
|
|
|
1. `LockKeys({a, b})`
|
|
|
|
|
2. `LockKeys({b})`
|
|
|
|
|
3. `LockKeys({c})`
|
|
|
|
|
|
|
|
|
|
То в критической секции одновременно могут находиться:
|
|
|
|
|
|
|
|
|
|
* 1 и 3
|
|
|
|
|
* 2 и 3
|
|
|
|
|
|
|
|
|
|
А вот 1 и 2 одновременно в критическую секцию зайти не могут, потому что у них множества ключей пересекаются.
|
|
|
|
|
|
|
|
|
|
Метод `LockKeys` должен блокироваться, пока не удастся
|
|
|
|
|
захватить все ключи, либо пока операция не будет
|
|
|
|
|
отменена через канал `cancel`.
|
|
|
|
|
|
2020-03-14 12:11:46 +00:00
|
|
|
|
```go
|
|
|
|
|
package keylock
|
|
|
|
|
|
|
|
|
|
type KeyLock interface {
|
|
|
|
|
// LockKeys locks all keys from provided set.
|
|
|
|
|
//
|
|
|
|
|
// Upon successful completion, function guarantees that no other call with intersecting set of keys
|
|
|
|
|
// will finish, until unlock() is called.
|
|
|
|
|
//
|
2020-03-19 17:55:01 +00:00
|
|
|
|
// If cancel channel is closed, function stops trying to lock received keys and returns immediately
|
2020-03-14 12:11:46 +00:00
|
|
|
|
LockKeys(keys []string, cancel <-chan struct{}) (canceled bool, unlock func())
|
|
|
|
|
}
|
2020-03-16 13:19:46 +00:00
|
|
|
|
```
|
|
|
|
|
|
2021-03-27 19:55:44 +00:00
|
|
|
|
Реализация не должна содержать busy wait. То есть, если вызов LockKeys не может выполниться,
|
2020-03-16 13:19:46 +00:00
|
|
|
|
потому что какие-то из ключей залочены другими горутинами, то текущая горутина
|
2021-03-27 19:55:44 +00:00
|
|
|
|
должна засыпать.
|