Sobes.tech
Back to questions
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
МТС CloudМТС Cloud

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)
    }
}

Или лучше организовать очередь и отдельный воркер для отправки, чтобы избежать гонок и блокировок.