GoLang RWMutex
Este tutorial demuestra cómo usar rwmutex
en GoLang.
GoLang RWMutex
Un mutex
es la abreviatura de exclusión mutua que se utiliza para rastrear qué subproceso ha accedido a una variable en cualquier momento. Los mutexes son la estructura de datos provista en el paquete sync
de GoLang.
Los mutexes
se utilizan al realizar concurrencia utilizando el código Go. Aquí hay un ejemplo simple del uso de mutex
en GoLang.
package main
import (
"fmt"
"sync"
"time"
)
func EvenNumber(num int) bool {
return num%2 == 0
}
func main() {
num := 2
var DemoMutex sync.Mutex
go func() {
DemoMutex.Lock()
defer DemoMutex.Unlock()
EvenNum := EvenNumber(num)
time.Sleep(5 * time.Millisecond)
if EvenNum {
fmt.Println("The number", num, " is even")
return
}
fmt.Println("The number", num, "is odd")
}()
go func() {
DemoMutex.Lock()
num++
DemoMutex.Unlock()
}()
time.Sleep(time.Second)
}
El código anterior verifica si el número es par o impar. Aquí, las gorrutinas
concurrentes pueden corromper los datos, por lo que usamos un mutex
para bloquear y desbloquear datos para evitar que se dañen.
Ver la salida:
The number 2 is even
El mutex
y RWmutex
son diferentes donde mutex
es un simple mutex, y RWmutex
es un bloqueo de exclusión mutua de lector-escritor. Con el RWMutex
, el bloqueo lo mantiene un número arbitrario de lectores o un escritor.
Cuando el valor de RWMutex
es cero, es un mutex desbloqueado. Probemos el mismo ejemplo con el mutex RWMutex
.
package main
import (
"fmt"
"sync"
"time"
)
func EvenNumber(num int) bool {
return num%2 == 0
}
func main() {
num := 2
var DemoRWM sync.RWMutex
// both goroutines call DemoRWM.Lock() before accessing `num` and then call the DemoRWM.Unlock after they are done
go func() {
DemoRWM.RLock()
defer DemoRWM.RUnlock()
EvenNum := EvenNumber(num)
time.Sleep(5 * time.Millisecond)
if EvenNum {
fmt.Println("The number", num, " is even")
return
}
fmt.Println("The number", num, "is odd")
}()
go func() {
DemoRWM.Lock()
num++
DemoRWM.Unlock()
}()
time.Sleep(time.Second)
}
Como podemos ver aquí, ambas goroutines
llaman a DemoRWM.Lock()
antes de acceder a num
y luego llaman a DemoRWM.Unlock
una vez que terminan. El código usa RWMutex
.
Ver la salida:
The number 2 is even
Probemos otro ejemplo para RWMutex
donde RWMutex
permite que todos los lectores accedan a los datos simultáneamente, y el escritor bloqueará a los demás.
Ver el ejemplo:
package main
import (
"fmt"
"sync"
)
func main() {
DemoMap := map[int]int{}
DemoRWM := &sync.RWMutex{}
go LoopWrite(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
// stop the program from exiting must be killed
StopBlock := make(chan struct{})
<-StopBlock
}
func LoopRead(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
for {
DemoRWM.RLock()
for k, v := range DemoMap {
fmt.Println(k, "-", v)
}
DemoRWM.RUnlock()
}
}
func LoopWrite(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
for {
for i := 0; i < 100; i++ {
DemoRWM.Lock()
DemoMap[i] = i
DemoRWM.Unlock()
}
}
}
Como vemos, el RWMutex
nos permite usar el leer
tantas veces como queramos; la salida de este código será algo como esto:
timeout running program
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
1 - 1
Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.
LinkedIn Facebook