dbHits++ нужно защитить синхронизацией. Для независимого счётчика удобно использовать atomic.Int64 и операции Add/Load.
Потокобезопасный счётчик dbHits через atomic.Int64
dbHits++ нужно защитить синхронизацией. Для независимого счётчика удобно использовать atomic.Int64 и операции Add/Load.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
type User struct {
ID int
Name string
}
var (
dbHits int
)
func getUserInfoFromDB(id int) User {
time.Sleep(100 * time.Millisecond)
dbHits++
return User{ID: id, Name: fmt.Sprintf("User-%d", id), }
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
fmt.Println(getUserInfoFromDB(i))
}(42)
}
wg.Wait()
fmt.Println("DB hits:", dbHits)
}
Исправьте ошибку в коде, связанную с конкурентным доступом к переменной dbHits.
Ответ
dbHits++ нужно защитить синхронизацией. Для независимого счётчика удобно использовать atomic.Int64 и операции Add/Load.
var dbHits atomic.Int64
func getUserInfoFromDB(id int) User {
time.Sleep(100 * time.Millisecond)
dbHits.Add(1)
return User{ID: id, Name: fmt.Sprintf("User-%d", id)}
}
// После wg.Wait():
// fmt.Println("DB hits:", dbHits.Load())
Добавьте импорт sync/atomic. При пяти успешных вызовах получится 5, порядок вывода пользователей не определён. Все горутины получают 42 намеренно по показанному вызову; исправление гонки не превращает одинаковые запросы в один и не добавляет кеширование.