Sobes.tech
Middle

Jakie typy mutexów zapewnia standardowa biblioteka Go?

sobes.tech AI

Odpowiedź od AI

Standardowa biblioteka Go zapewnia dwa główne typy mutexów w pakiecie sync:

  • sync.Mutex: Podstawowy mutex zapewniający wykluczenie wzajemne. Może być w dwóch stanach: zablokowany lub odblokowany. Tylko jedna gorutyna może utrzymywać blokadę w danym momencie.
  • sync.RWMutex: Mutex do odczytu/zapisu. Pozwala wielu gorutynom odczytywać dane jednocześnie (poprzez RLock), ale tylko jednej na zapis (poprzez Lock). Zapis blokuje wszystkie operacje (zarówno odczyt, jak i zapis).

Główne metody sync.Mutex:

Metoda Opis
Lock() Blokuje mutex. Jeśli jest już zablokowany, wywołująca gorutyna zostaje zablokowana do czasu odblokowania.
Unlock() Odblokowuje mutex. Panika, jeśli mutex nie był zablokowany przez wywołującą gorutynę.

Główne metody sync.RWMutex:

Metoda Opis
Lock() Blokuje mutex do zapisu. Blokuje wszystkie operacje odczytu i zapisu.
Unlock() Odblokowuje mutex do zapisu. Panika, jeśli mutex nie był zablokowany do zapisu.
RLock() Blokuje mutex do odczytu. Nie blokuje innych operacji odczytu. Zablokuje się, jeśli istnieje blokada zapisu.
RUnlock() Odblokowuje mutex do odczytu. Panika, jeśli mutex nie był zablokowany do odczytu.
RLocker() Zwraca Locker, który używa RLock i RUnlock.

Przykład użycia sync.Mutex:

package main

import (
	"fmt"
	"sync"
	"time"
)

var counter int
var mutex sync.Mutex

func increment() {
	mutex.Lock() // Blokuje mutex
	counter++
	fmt.Printf("Counter: %d\n", counter)
	mutex.Unlock() // Odblokowuje mutex
}

func main() {
	for i := 0; i < 10; i++ {
		go increment()
	}
	time.Sleep(time.Second) // Daje czas gorutynom na zakończenie
}

Przykład użycia sync.RWMutex:

package main

import (
	"fmt"
	"sync"
	"time"
)

var data string
var rwMutex sync.RWMutex

func readData() {
	rwMutex.RLock() // Blokuje do odczytu
	fmt.Printf("Odczyt danych: %s\n", data)
	rwMutex.RUnlock() // Odblokowuje do odczytu
}

func writeData(newData string) {
	rwMutex.Lock() // Blokuje do zapisu
	data = newData
	fmt.Printf("Zapis danych: %s\n", data)
	rwMutex.Unlock() // Odblokowuje do zapisu
}

func main() {
	go writeData("Cześć")
	time.Sleep(100 * time.Millisecond) // Daje czas na zapis

	for i := 0; i < 5; i++ {
		go readData() // Dozwolone wiele równoczesnych odczytów
	}

	time.Sleep(time.Second) // Daje czas na zakończenie gorutyn
	go writeData("Świat")
	time.Sleep(100 * time.Millisecond)
	go readData()

	time.Sleep(time.Second)
}