Назад к вопросам
Middle
104
questionbank

Какие типы мьютексов предоставляет стандартная библиотека Go?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Стандартная библиотека Go предоставляет два основных типа мьютексов в пакете sync:

  • sync.Mutex: Базовый мьютекс, обеспечивающий взаимоисключающую блокировку. Может быть в двух состояниях: заблокирован или разблокирован. Только одна горутина может удерживать блокировку в любой момент времени.
  • sync.RWMutex: Мьютекс для чтения/записи. Позволяет множеству горутин одновременно читать данные (получать RLock), но только одной горутине писать данные (получать Lock). Запись блокирует все операции (как чтение, так и запись).

Основные методы sync.Mutex:

Метод Описание
Lock() Блокирует мьютекс. Если мьютекс уже заблокирован, вызывающая горутина блокируется до его освобождения.
Unlock() Разблокирует мьютекс. Паника, если мьютекс не был заблокирован вызывающей горутиной.

Основные методы sync.RWMutex:

Метод Описание
Lock() Блокирует мьютекс для записи. Блокирует все операции чтения и записи.
Unlock() Разблокирует мьютекс для записи. Паника, если мьютекс не был заблокирован для записи.
RLock() Блокирует мьютекс для чтения. Не блокирует другие операции чтения. Блокируется, если есть блокировка записи.
RUnlock() Разблокирует мьютекс для чтения. Паника, если мьютекс не был заблокирован для чтения.
RLocker() Возвращает Locker, который использует RLock и RUnlock.

Пример использования sync.Mutex:

package main

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

var counter int
var mutex sync.Mutex

func increment() {
	mutex.Lock() // Блокируем мьютекс
	counter++
	fmt.Printf("Counter: %d\n", counter)
	mutex.Unlock() // Разблокируем мьютекс
}

func main() {
	for i := 0; i < 10; i++ {
		go increment()
	}
	time.Sleep(time.Second) // Даем время горутинам завершиться
}

Пример использования sync.RWMutex:

package main

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

var data string
var rwMutex sync.RWMutex

func readData() {
	rwMutex.RLock() // Блокируем для чтения
	fmt.Printf("Reading data: %s\n", data)
	rwMutex.RUnlock() // Разблокируем для чтения
}

func writeData(newData string) {
	rwMutex.Lock() // Блокируем для записи
	data = newData
	fmt.Printf("Writing data: %s\n", data)
	rwMutex.Unlock() // Разблокируем для записи
}

func main() {
	go writeData("Hello")
	time.Sleep(100 * time.Millisecond) // Даем время на запись

	for i := 0; i < 5; i++ {
		go readData() // Множество одновременных чтений разрешены
	}

	time.Sleep(time.Second) // Даем время горутинам завершиться
	go writeData("World")
	time.Sleep(100 * time.Millisecond)
	go readData()

	time.Sleep(time.Second)
}