🗣️Mutexes Golang

Mutexes en Go

En programas concurrentes, múltiples goroutines pueden intentar acceder y modificar datos compartidos al mismo tiempo, lo que puede llevar a problemas como condiciones de carrera.

Los mutexes en Go proporcionan una manera de garantizar que solo una goroutine pueda acceder a una sección crítica del código a la vez, asegurando así la integridad de los datos.

Un mutex es un objeto que permite a las goroutines adquirir y liberar un bloqueo sobre un recurso compartido. Esto asegura que solo una goroutine pueda acceder a ese recurso en un momento dado.

¿Qué es un Mutex en Go?

Un mutex, o mutual exclusion (exclusión mutua), es una primitiva de sincronización que se utiliza para proteger el acceso a recursos compartidos en un entorno concurrente. En Go, el paquete sync proporciona el tipo Mutex, que permite bloquear y desbloquear el acceso a estos recursos.

Concepto Básico de Funcionamiento:

  • Lock: Una goroutine adquiere el mutex, bloqueando el acceso a la sección crítica. Ninguna otra goroutine puede acceder a esta sección mientras el mutex esté bloqueado.

  • Unlock: Una vez que la goroutine termina de usar el recurso compartido, libera el mutex, permitiendo que otras goroutines adquieran el bloqueo.

Sintaxis Básica de un Mutex en Go

package main

import (
    "fmt"
    "sync"
)

var contador int
var mutex sync.Mutex

func incrementar() {
    mutex.Lock()   // Bloquea el mutex para asegurar acceso exclusivo
    contador++
    mutex.Unlock() // Desbloquea el mutex
}

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            incrementar()
        }()
    }

    wg.Wait()
    fmt.Println("Valor final del contador:", contador)
}

Explicación del Código:

  1. Declaración de Variables:

  • contador: Un entero que será incrementado por múltiples goroutines.

  • mutex: Una instancia de sync.Mutex que protegerá el acceso a contador.

  1. Función incrementar:

  • mutex.Lock(): La goroutine que ejecuta incrementar adquiere el mutex, bloqueando el acceso a contador.

  • Incremento del contador: Una vez que el mutex está bloqueado, se incrementa contador de manera segura.

  • mutex.Unlock(): La goroutine libera el mutex, permitiendo que otras goroutines lo adquieran.

  1. Uso de WaitGroup:

  • sync.WaitGroup se utiliza para esperar a que todas las goroutines terminen antes de imprimir el valor final de contador.

  1. Resultado Esperado:

  • Dado que mutex asegura que solo una goroutine puede modificar contador a la vez, el valor final será 1000, garantizando que no haya condiciones de carrera.

Salida esperada:

Valor final del contador: 1000

Otro ejemplo de código:

package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu  sync.Mutex
)

func increment(wg *sync.WaitGroup) {
    defer wg.Done()
    mu.Lock()         // Adquiere el bloqueo
    counter++         // Acceso al recurso compartido
    mu.Unlock()       // Libera el bloqueo
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go increment(&wg)
    }
    wg.Wait()
    fmt.Println("Counter:", counter)
}

Data Race en Golang

  1. Definición:

    • Un data race ocurre cuando dos o más goroutines acceden a la misma variable simultáneamente y al menos uno de los accesos es una escritura. Esto puede llevar a resultados inesperados y comportamientos erráticos en el programa.

Last updated