В чем разница между RLock () и Lock () в Golang? - PullRequest
0 голосов
/ 22 ноября 2018

В чем разница между RLock () и Lock () в Golang и как их можно эффективно использовать, когда мы используем mutex Lock?

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Lock () : только одно чтение и запись одной процедуры за раз путем получения блокировки.

RLock () : чтение нескольких операций может (не записывать) за один раз путем получения блокировки.

package main

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

func main() {

    a := 0

    lock := sync.RWMutex{}

    for i := 1; i < 10; i++ {
        go func(i int) {
            lock.Lock()
            fmt.Printf("Lock: from go routine %d: a = %d\n",i, a)
            time.Sleep(time.Second)
            lock.Unlock()
        }(i)
    }

    b := 0

    for i := 11; i < 20; i++ {
        go func(i int) {
            lock.RLock()
            fmt.Printf("RLock: from go routine %d: b = %d\n",i, b)
            time.Sleep(time.Second)
            lock.RUnlock()
        }(i)
    }

    <-time.After(time.Second*10)
}

1) Когда подпрограмма go уже получила RLock (), может ли другая подпрограмма go получить Lock () для записи или она имеетждать, пока не произойдет RUnlock ()?

  • Чтобы получить блокировку () для записи, нужно подождать, пока RUnlock ()

2) Что происходит, когда кто-то уже приобрелLock () для карты, будет ли другая подпрограмма go по-прежнему получать RLock ()

  • , если кто-то X уже приобрел Lock (), тогда другой подпрограмме для получения RLock () придется подождать, покаБлокировка разблокировки X (Unlock ())

3) Если предположить, что мы имеем дело с Картами здесь, возможна ли ошибка «одновременного чтения / записи карты»?

  • Карта не является поточно-ориентированной.поэтому «одновременное чтение / запись карты» может привести к ошибке.

См. следующий пример для получения дополнительной информации:

package main

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

func main() {
    lock := sync.RWMutex{}

    b := map[string]int{}
    b["0"] = 0

    go func(i int) {
        lock.RLock()
        fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["0"])
        time.Sleep(time.Second*3)
        fmt.Printf("RLock: from go routine %d: lock released\n",i)
        lock.RUnlock()
    }(1)

    go func(i int) {
        lock.Lock()
        b["2"] = i
        fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["2"])
        time.Sleep(time.Second*3)
        fmt.Printf("Lock: from go routine %d: lock released\n",i)
        lock.Unlock()
    }(2)

    <-time.After(time.Second*8)

    fmt.Println("*************************************8")

    go func(i int) {
        lock.Lock()
        b["3"] = i
        fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["3"])
        time.Sleep(time.Second*3)
        fmt.Printf("Lock: from go routine %d: lock released\n",i)
        lock.Unlock()
    }(3)

    go func(i int) {
        lock.RLock()
        fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["3"])
        time.Sleep(time.Second*3)
        fmt.Printf("RLock: from go routine %d: lock released\n",i)
        lock.RUnlock()
    }(4)

    <-time.After(time.Second*8)
}
0 голосов
/ 22 ноября 2018

RWMutex - блокировка взаимоисключения чтения / записи.Блокировка может быть проведена произвольным числом читателей или одним писателем.Нулевое значение для RWMutex - это разблокированный мьютекс.

RWMutex не должен копироваться после первого использования.

Если в программе есть RWMutex для чтения, а другая программа может вызвать Lock, no goroutineследует ожидать возможности получить блокировку чтения до тех пор, пока не будет снята первоначальная блокировка чтения.В частности, это запрещает рекурсивную блокировку чтения.Это сделано для того, чтобы блокировка в конечном итоге стала доступной;заблокированный вызов блокировки не позволяет новым читателям получить блокировку.


Mutex - это блокировка взаимного исключения.Нулевое значение для Mutex - это разблокированный мьютекс.

Golang предоставляет канал - лучшая практика для управления параллелизмом, поэтому я думаю, что эффективный способ использования sync.lock не использует его, вместо этого используйте канал.

...