Sobes.tech
Middle

Jaké typy mutexů poskytuje standardní knihovna Go?

sobes.tech AI

Odpověď od AI

Standardní knihovna Go poskytuje dva hlavní typy zámků v balíčku sync:

  • sync.Mutex: Základní zámek, který zajišťuje vzájemné vyloučení. Může být ve dvou stavech: zamčený nebo odemčený. Pouze jedna gorutina může současně držet zámek.
  • sync.RWMutex: Zámek pro čtení/zápis. Umožňuje více gorutinám současně číst data (pomocí RLock), ale pouze jedné zapisovat (pomocí Lock). Zápis blokuje všechny operace (čtení i zápis).

Hlavní metody sync.Mutex:

Metoda Popis
Lock() Zamkne zámek. Pokud je již zamčený, volající gorutina čeká na odemčení.
Unlock() Odemyká zámek. Vyvolá se panic, pokud zámek nebyl zamčený volající gorutinou.

Hlavní metody sync.RWMutex:

Metoda Popis
Lock() Zamkne zámek pro zápis. Blokuje všechny operace čtení i zápisu.
Unlock() Odemyká zámek pro zápis. Vyvolá se panic, pokud zámek nebyl zamčený pro zápis.
RLock() Zamkne zámek pro čtení. Neblokuje jiné operace čtení. Blokuje, pokud je zámek zamčený pro zápis.
RUnlock() Odemyká zámek pro čtení. Vyvolá se panic, pokud zámek nebyl zamčený pro čtení.
RLocker() Vrací Locker, který používá RLock a RUnlock.

Příklad použití sync.Mutex:

package main

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

var counter int
var mutex sync.Mutex

func increment() {
	mutex.Lock() // Zamknutí zámku
	counter++
	fmt.Printf("Counter: %d\n", counter)
	mutex.Unlock() // Odemykání zámku
}

func main() {
	for i := 0; i < 10; i++ {
		go increment()
	}
	time.Sleep(time.Second) // Čekáme na dokončení gorutin
}

Příklad použití sync.RWMutex:

package main

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

var data string
var rwMutex sync.RWMutex

func readData() {
	rwMutex.RLock() // Zamknutí pro čtení
	fmt.Printf("Čtení dat: %s\n", data)
	rwMutex.RUnlock() // Odemykání pro čtení
}

func writeData(newData string) {
	rwMutex.Lock() // Zamknutí pro zápis
	data = newData
	fmt.Printf("Zápis dat: %s\n", data)
	rwMutex.Unlock() // Odemykání pro zápis
}

func main() {
	go writeData("Hello")
	time.Sleep(100 * time.Millisecond) // Čekáme na zápis

	for i := 0; i < 5; i++ {
		go readData() // Více současných čtení je povoleno
	}

	time.Sleep(time.Second) // Čekáme na dokončení gorutin
	go writeData("World")
	time.Sleep(100 * time.Millisecond)
	go readData()

	time.Sleep(time.Second)
}