Метод sync.RWMutex.RUnlock

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

Важно помнить, что вызов RUnlock без предварительного вызова RLock приводит к панике во время выполнения программы. Поэтому всегда нужно использовать RUnlock в паре с RLock.

Синтаксис

gomu.RUnlock()

Пример

Давайте рассмотрим базовый пример использования RUnlock для освобождения блокировки чтения:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var mu sync.RWMutex
  data := "initial value"

  mu.RLock()
  fmt.Println("Reading data:", data)
  mu.RUnlock()
}

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

go"Reading data: initial value"

Пример

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

gopackage main

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

func main() {
  var mu sync.RWMutex
  counter := 0
  var wg sync.WaitGroup

  for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(id int) {
      defer wg.Done()

      mu.RLock()
      fmt.Printf("Goroutine %d read: %d\n", id, counter)
      mu.RUnlock()
    }(i)
  }

  wg.Wait()
}

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

go"Goroutine 4 read: 0"
"Goroutine 0 read: 0"
"Goroutine 1 read: 0"
"Goroutine 2 read: 0"
"Goroutine 3 read: 0"

Пример

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

gopackage main

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

func main() {
  var mu sync.RWMutex
  value := "initial"
  var wg sync.WaitGroup

  wg.Add(3)

  go func() {
    defer wg.Done()
    mu.RLock()
    fmt.Println("Reader 1:", value)
    mu.RUnlock()
  }()

  go func() {
    defer wg.Done()
    time.Sleep(100 * time.Millisecond)

    mu.Lock()
    value = "updated"
    fmt.Println("Writer updated value")
    mu.Unlock()
  }()

  go func() {
    defer wg.Done()
    time.Sleep(50 * time.Millisecond)

    mu.RLock()
    fmt.Println("Reader 2:", value)
    mu.RUnlock()
  }()

  wg.Wait()
}

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

go"Reader 1: initial"
"Reader 2: initial"
"Writer updated value"

Пример

Давайте рассмотрим пример использования RUnlock с отложенным вызовом через defer для обеспечения безопасного освобождения блокировки:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var mu sync.RWMutex
  data := []string{"a", "b", "c", "d", "e"}

  readData := func() {
    mu.RLock()
    defer mu.RUnlock()

    for i, v := range data {
      fmt.Printf("Index %d: %s\n", i, v)
    }
  }

  readData()
}

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

go"Index 0: a"
"Index 1: b"
"Index 2: c"
"Index 3: d"
"Index 4: e"

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

  • метод sync.RWMutex.RLock,
    который захватывает блокировку чтения
  • метод sync.RWMutex.Lock,
    который захватывает блокировку записи
  • метод sync.RWMutex.Unlock,
    который освобождает блокировку записи
  • структуру sync.RWMutex,
    которая реализует блокировки чтения-записи