Senior
// Küsimus 3 // Kirjeldage, millist ülesannet see kood lahendab // Millised probleemid on selles lahenduses? // Kuidas te selle koodi ümber kirjutaksite? var c int var mu sync.RWMutex type Trace struct { // Mõned väljad siin } 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 } }
sobes.tech AI
Vastus AI-lt
Этот код пытается считать вызовы функции 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)
}
}
Или лучше организовать очередь и отдельный воркер для отправки, чтобы избежать гонок и блокировок.