0Pricing
Go Academy · Lekcja

sync.Mutex i sync.RWMutex

Wzorce blokad oraz blokad odczytu i zapisu

sync.Mutex i sync.RWMutex to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.

Dlaczego muteksy?

Gdy wiele gorutyn współdzieli zmienny stan, równoczesne odczyty i zapisy powodują wyścigi danych. Mutex szeregowo porządkuje dostęp, dzięki czemu w danej chwili tylko jedna gorutyna wchodzi do sekcji krytycznej.

Podstawy sync.Mutex

Przed odczytem lub zapisem współdzielonego stanu należy wywołać Lock, a po nim Unlock. Należy użyć defer, aby zagwarantować odblokowanie nawet wtedy, gdy funkcja wywoła panic.

var mu sync.Mutex
var counter int

func inc() {
    mu.Lock()
    defer mu.Unlock()
    counter++
}

Osadzanie Mutex w strukturze

Mutex należy osadzić w strukturze, którą chroni. Zgodnie z przyjętą konwencją mutex deklaruje się bezpośrednio nad polami, które chroni.

type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.v[key]++
}

Nie należy kopiować Mutex

Mutex nie wolno kopiować po pierwszym użyciu. Należy przekazywać go przez wskaźnik albo osadzić w strukturze przekazywanej przez wskaźnik. Narzędzie go vet wykrywa kopie.

sync.RWMutex

sync.RWMutex pozwala wielu czytelnikom działać współbieżnie, ale dopuszcza tylko jednego autora. Należy go używać, gdy odczyty dominują, a zapisy są rzadkie, aby zwiększyć przepustowość.

var rw sync.RWMutex
var data map[string]int

func read(k string) int {
    rw.RLock()
    defer rw.RUnlock()
    return data[k]
}
func write(k string, v int) {
    rw.Lock()
    defer rw.Unlock()
    data[k] = v
}

RLock a Lock

RLock uzyskuje blokadę odczytu (współdzieloną), a Lock uzyskuje blokadę zapisu (wyłączną). Oczekująca blokada zapisu blokuje nowe blokady odczytu, zapobiegając zagłodzeniu autora.

TryLock (Go 1.18+)

mu.TryLock() uzyskuje blokadę tylko wtedy, gdy nie jest ona obecnie zajęta, i zwraca wartość logiczną. Jest przydatny, gdy blokowanie jest niedopuszczalne.

if mu.TryLock() {
    defer mu.Unlock()
    // critical section
}

Zakleszczenia

Zakleszczenie występuje, gdy gorutyna A posiada blokadę 1 i czeka na blokadę 2, a gorutyna B posiada blokadę 2 i czeka na blokadę 1. Zawsze należy uzyskiwać blokady w tej samej kolejności i utrzymywać sekcje krytyczne w krótkim czasie.

Ziarnistość blokad

Blokada gruboziarnista jest łatwiejsza do analizowania, ale ogranicza współbieżność. Blokady drobnoziarniste zwiększają przepustowość, lecz podnoszą złożoność i ryzyko zakleszczeń. Należy zacząć od blokady gruboziarnistej i optymalizować dopiero wtedy, gdy profilowanie wykaże rywalizację o zasoby.

Mutex a kanał

Mutex należy stosować do ochrony współdzielonego stanu, z którym pracuje wielu czytelników i autorów. Kanału należy używać do przekazywania własności danych między gorutynami. Kanały służą do komunikacji, a muteksy do synchronizacji.

Interfejs sync.Locker

sync.Locker to interfejs zawierający Lock i Unlock. Zarówno Mutex, jak i RWMutex go implementują, dzięki czemu funkcje pomocnicze mogą przyjmować dowolny z tych typów.

Szybki test

Kiedy należy użyć sync.RWMutex zamiast sync.Mutex?

Podsumowanie: Mutex i RWMutex

Najważniejsze informacje:

  • Mutex serializuje dostęp; zawsze wywołuj Unlock za pomocą defer
  • Nie kopiuj Mutex po pierwszym użyciu
  • RWMutex: wielu czytelników LUB jeden zapisujący
  • Blokady należy uzyskiwać w spójnej kolejności, aby uniknąć zakleszczeń

Często zadawane pytania

Czy lekcja „sync.Mutex i sync.RWMutex” jest bezpłatna?

Tak — pełny tekst „sync.Mutex i sync.RWMutex” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „sync.Mutex i sync.RWMutex”?

Wzorce blokad oraz blokad odczytu i zapisu Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Go Academy?

Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „sync.Mutex i sync.RWMutex”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?

Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. sync.Mutex i sync.RWMutex
  2. sync.WaitGroup
  3. sync.Once i sync.Map
  4. Detektor wyścigów i bezpieczne wzorce
← Powrót do Go Academy