W Go mapy (map) nie są domyślnie bezpieczne dla wątków. Jeśli kilka gorutyn jednocześnie zapisuje lub odczytuje tę samą mapę bez synchronizacji, powstanie stan wyścigu (data race), co prowadzi do paniki fatal error: concurrent map read and map write lub uszkodzenia danych.
Aby bezpiecznie pracować z mapą, należy:
sync.Map, który jest przeznaczony do wysokoobciążonych scenariuszy współbieżnych.var mu sync.RWMutex m := make(map[string]int) // Zapis mu.Lock() m["key"] = 1 mu.Unlock() // Odczyt mu.RLock() v := m["key"] mu.RUnlock() // Lub sync.Map var sm sync.Map sm.Store("key", 1) v, _ := sm.Load("key")
Dlaczego jednoczesne odczyty i zapisy z różnych gorutyn do mapy w Go są tak niebezpieczne, jeśli mapa to wbudowany typ?
Odpowiedź: W Go wbudowany typ mapa nie zapewnia synchronizacji. Jednoczesny dostęp do mapy z kilku gorutyn powoduje nie tylko niepoprawne wartości, ale może także prowadzić do awarii programu. Nawet jednoczesny odczyt i zapis (gdy klucze się nie pokrywają!) może spowodować błąd krytyczny. To różni się od niektórych innych języków, w których kolekcje są „tolerancyjne” na konkurencyjne operacje.
Historia
W prawdziwym projekcie programista użył globalnej mapy do buforowania danych. Serwis działał stabilnie na testach, ale podczas testów obciążeniowych i w produkcji zaczął się kruszyć z błędem fatal error: concurrent map read and map write. Przyczyną był równoległy dostęp do mapy z różnych zapytań http bez użycia Mutex.
Historia
W aplikacji webowej Go jeden programista postanowił poprawić wydajność i użył zwykłej mapy jako puli połączeń, zakładając, że wielowątkowość jest zapewniana przez framework. Przy nagłym wzroście ruchu serwis zaczął się kruszyć bez wyraźnej przyczyny: z powodu stanu wyścigu dane w mapie były uszkadzane i występowały paniki.
Historia
W wewnętrznej usłudze Go aplikacja używała mapy do zbierania statystyk „w locie”, sądząc, że główne operacje dotyczą tylko zapisu. W rzeczywistości inna część kodu okresowo żądała danych do tworzenia raportów, co prowadziło do trudnych do zauważenia awarii tylko raz dziennie — akurat wtedy, gdy uruchamiała się statystyka. Analiza wykazała, że odczyty i zapisy nakładały się na siebie bez jakiejkolwiek blokady.