Sobes.tech
Senior

// 3. kérdés // Írja le, milyen feladatot old meg ez a kód // Milyen problémák vannak ebben a megoldásban? // Hogyan írnád át ezt a kódot? var c int var mu sync.RWMutex type Trace struct { // Néhány mező itt } 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 MI

Válasz az MI-től

Этот код пытается считать вызовы функции 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)
    }
}

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