Sobes.tech
Middle

Jakie mutexy używasz, aby zapewnić bezpieczeństwo podczas pracy z mapami w Go?

sobes.tech AI

Odpowiedź od AI

Aby zapewnić bezpieczeństwo podczas pracy z niekonkurencyjnym dostępem do struktur danych, w tym map (map), w Go używa się mutexów z pakietu sync.

  • sync.Mutex: Podstawowy mutex do wyłącznej blokady. Używany do blokowania i odblokowywania sekcji kodu, w których odczyt lub zapis odbywa się na mapie.
  • sync.RWMutex: Mutex z dostępem współdzielonym (czytanie) i wyłącznym (zapis). Pozwala wielu gorutynom czytać z mapy jednocześnie, ale tylko jednej zapisywać. Idealny w scenariuszach, gdzie odczytów jest znacznie więcej niż zapisów.

Preferowanym rozwiązaniem do współbieżnej i bezpiecznej pracy z mapami jest sync.RWMutex, ponieważ zapewnia lepszą wydajność przy wielu równoczesnych operacjach odczytu.

Przykład użycia sync.RWMutex:

import (
	"sync"
)

type SafeMap struct {
	mu sync.RWMutex
	m  map[string]int
}

func NewSafeMap() *SafeMap {
	return &SafeMap{
		m: make(map[string]int),
	}
}

func (sm *SafeMap) Set(key string, value int) {
	sm.mu.Lock()   // Blokada do zapisu
	defer sm.mu.Unlock()
	sm.m[key] = value
}

func (sm *SafeMap) Get(key string) (int, bool) {
	sm.mu.RLock()  // Blokada do odczytu
	defer sm.mu.RUnlock()
	value, ok := sm.m[key]
	return value, ok
}

Istnieje również specjalistyczny typ sync.Map, który jest zoptymalizowany do użycia w środowiskach współbieżnych bez jawnego blokowania mutexami w większości przypadków, ale ma pewne ograniczenia i inną API. Jednakże, jeśli potrzebna jest bardziej elastyczna kontrola nad blokadami lub specyficzne scenariusze dostępu, użycie sync.RWMutex na standardowej mapie jest powszechną praktyką.