Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Mutex de lectura y escritura

4/19
Recursos

Aportes 4

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Solo para aclarar las diferencias entre RWLock y no usar nada:

  • Lock bloquea lecturas (con RLock) y escrituras (con Lock) de otras goroutines
  • Unlock permite nuevas lecturas (con Rlock) y/o otra escritura (con Lock)
  • RLock bloquea escrituras (Lock) pero no bloquea lecturas (RLock)
  • RUnlock permite nuevas escrituras (y también lecturas, pero por la naturaleza de RLock, estas no se vieron bloqueadas nunca)

En esencia, RLock de RWLock garantiza una secuencia de lecturas en donde el valor que lees no se verá alterado por nuevos escritores, a diferencia de no usar nada.

Sacado de aquí mero

Es mejor renombrar lock a mux para evitar lo que se conoce en Go como tartamudeo lock.Lock().

Refactoricé el ejemplo para que se muestre el balance en cada iteración del ciclo, se puede evidenciar que las lecturas se realizan mucho más rápido que las escrituras. Esto es esperable por tener muchas go routinas leyendo al mismo tiempo, pero solo una escribiendo a la vez.

La cuenta arranca con cero y va sumando i desde 1 hasta 20, segun la fórmula de Gauss la cuenta debe dar 210.

package main

import (
	"fmt"
	"sync"
)

var (
	balance int = 0
)

// Writer
func Deposit(amount int, wg *sync.WaitGroup, lock *sync.RWMutex) {
	defer wg.Done()
	defer lock.Unlock()

	lock.Lock()
	b := balance
	balance = b + amount
}

// Reader
func Balance(wg *sync.WaitGroup, lock *sync.RWMutex) {
	defer wg.Done()
	defer lock.RUnlock()
	lock.RLock()
	b := balance
	fmt.Println("Current balance is", b)
}

func main() {
	var wg sync.WaitGroup
	var lock sync.RWMutex

	for i := 1; i <= 20; i++ {
		wg.Add(1)
		go Deposit(i, &wg, &lock)
		wg.Add(1)
		go Balance(&wg, &lock)

	}

	wg.Wait()
	fmt.Println("Finished with balance", balance)
}

Obtiene como salida:

Current balance is 3
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 6
Current balance is 11
Current balance is 11
Current balance is 11
Current balance is 11
Current balance is 11
Current balance is 11
Current balance is 11
Finished with balance 210
package main

import "sync"

// Problem: Race condition
// build: go build --race main.go

var (
	balance int = 100
)

func Deposit(amount int, wg *sync.WaitGroup, lock *sync.RWMutex) {
	defer wg.Done()
	defer lock.Unlock() // Unlock is a method of the Mutex struct

	lock.Lock() // Lock the mutex
	b := balance
	balance = b + amount
}

func Balance(lock *sync.RWMutex) int {
	lock.RLock()
	b := balance
	lock.RUnlock()
	return b
}

// 1 Deposit() -> Escribir (Race Condition)
// N Balance() -> Leer

func main() {
	var wg sync.WaitGroup
	var lock sync.RWMutex // Mutex is a struct that implements the Lock and Unlock methods

	for i := 1; i <= 5; i++ {
		wg.Add(1)
		go Deposit(i*100, &wg, &lock)
	}

	wg.Wait()
	println(Balance(&lock))
}