Реализуйте потокобезопасную map с шардированием на 32 шарда. Один общий
мьютекс на всю map становится точкой контеншена под высокой нагрузкой; разбиение
на шарды (каждый со своим мьютексом) позволяет горутинам, работающим с разными
ключами, не блокировать друг друга.
type ShardedMap struct {
// 32 шарда, у каждого свой RWMutex
}
func NewShardedMap() *ShardedMap
func (m *ShardedMap) Set(key string, value interface{})
func (m *ShardedMap) Get(key string) (interface{}, bool)
func (m *ShardedMap) Delete(key string)
func (m *ShardedMap) Len() int
Номер шарда вычисляется по хешу ключа (например, FNV). Каждый шард защищён
своим sync.RWMutex: чтения берут RLock, записи — Lock.
В тесте множество горутин конкурентно выполняют Set/Get/Delete. Проверяется
функциональная корректность (что записали — то и прочитали), а также что
большое число ключей распределяется более чем по одному шарду. Проверка идёт
под детектором гонок (-race).
На что смотрит интервьюер:
- Разбиение на 32 независимых шарда, каждый со своим
sync.RWMutex.
- Детерминированный выбор шарда по хешу ключа (FNV или аналог), один и тот же
ключ всегда попадает в один шард.
Get под RLock, Set/Delete под Lock — без гонок под -race.
Len() корректно суммирует размеры всех шардов (с захватом блокировок).
- Кандидат понимает, зачем шардирование: снижение контеншена на мьютексе.