Back to questions
МТС Cloud
Senior
3
// Задача 3 // Описать какую задачу решает данный код // Какие проблемы есть в этом решении? // Как бы вы переписали этот код? var c int var mu sync.RWMutex type Trace struct { // Some fields here } type Sender interface { Send(Trace) } func Do(sender Sender, tr Trace) { mu.Lock() defer mu.Unlock() c++ if c == 100 { go func() { sender.Send(tr) }() c = 0 } }
Companies where asked
Answer from AI
sobes.tech AI
Этот код пытается считать вызовы функции Do и при достижении 100 вызвать метод Send у интерфейса Sender в отдельной горутине, после чего сбросить счётчик.
Проблемы:
- Используется глобальная переменная c и мьютекс mu, что создаёт узкое место и снижает параллелизм.
- Вызов sender.Send(tr) происходит в горутине, но при этом tr передаётся по значению, что может привести к рассинхронизации данных.
- Сброс счётчика c = 0 происходит внутри заблокированного участка, что может привести к задержкам.
- Нет обработки ошибок или подтверждения успешной отправки.
Как переписать:
- Использовать атомарный счётчик вместо мьютекса для повышения производительности.
- Вынести вызов Send из критической секции.
- Возможно, использовать канал для передачи данных в отдельный воркер, который будет обрабатывать отправку.
Пример улучшенного варианта:
var c int32
type Trace struct {
// поля
}
type Sender interface {
Send(Trace)
}
func Do(sender Sender, tr Trace) {
newCount := atomic.AddInt32(&c, 1)
if newCount == 100 {
atomic.StoreInt32(&c, 0)
go sender.Send(tr)
}
}
Или лучше организовать очередь и отдельный воркер для отправки, чтобы избежать гонок и блокировок.