РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
836 of 1593 menu

Тип sync.RWMutex

Тип sync.RWMutex — это мьютекс с возможностью разделяемой блокировки для чтения. Он позволяет множественным горутинам одновременно получать доступ на чтение, но блокирует доступ на запись во время операций чтения. Такой подход значительно повышает производительность при частом чтении данных и редкой записи.

У типа sync.RWMutex есть два основных метода для блокировки: RLock для чтения и Lock для записи. Для снятия блокировок используются методы RUnlock и Unlock соответственно.

Синтаксис

var mu sync.RWMutex // Для чтения mu.RLock() // чтение данных mu.RUnlock() // Для записи mu.Lock() // запись данных mu.Unlock()

Пример использования RWMutex для чтения

Давайте создадим структуру счетчика с разделяемым доступом и организуем одновременное чтение данных:

package main import ( "fmt" "sync" ) type Counter struct { mu sync.RWMutex value int } func (c *Counter) Read() int { c.mu.RLock() defer c.mu.RUnlock() return c.value } func main() { counter := &Counter{value: 42} var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() res := counter.Read() fmt.Println(res) }() } wg.Wait() }

Результат выполнения кода:

"42" "42" "42" "42" "42"

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

Теперь добавим метод записи и проверим, как блокировка на запись влияет на чтение:

package main import ( "fmt" "sync" ) type Counter struct { mu sync.RWMutex value int } func (c *Counter) Write(val int) { c.mu.Lock() defer c.mu.Unlock() c.value = val fmt.Println("Written:", val) } func (c *Counter) Read() int { c.mu.RLock() defer c.mu.RUnlock() return c.value } func main() { counter := &Counter{value: 10} var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() counter.Write(99) }() wg.Add(1) go func() { defer wg.Done() res := counter.Read() fmt.Println("Read:", res) }() wg.Wait() }

Результат выполнения кода (порядок может отличаться):

"Written: 99" "Read: 99"

Пример с несколькими читателями и одним писателем

Покажем, как RWMutex позволяет одновременно читать данные нескольким горутинам, но блокирует запись:

package main import ( "fmt" "sync" "time" ) func main() { var mu sync.RWMutex data := "initial" // Читатели for i := 0; i < 3; i++ { go func(id int) { mu.RLock() fmt.Printf("Reader %d: %s\n", id, data) time.Sleep(100 * time.Millisecond) mu.RUnlock() }(i) } // Писатель time.Sleep(50 * time.Millisecond) go func() { mu.Lock() data = "updated" time.Sleep(200 * time.Millisecond) mu.Unlock() }() time.Sleep(500 * time.Millisecond) }

Результат выполнения кода (порядок строк может отличаться):

"Reader 2: initial" "Reader 0: initial" "Reader 1: initial"

Смотрите также

  • тип sync.Mutex,
    который предоставляет обычную блокировку без разделения на чтение/запись
  • метод RLock,
    который блокирует мьютекс для чтения
  • метод Lock,
    который блокирует мьютекс для записи
  • пакет atomic,
    который предоставляет атомарные операции для конкурентного доступа без блокировок
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить