# 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**

```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:

```go
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.

<figure><img src="https://2827710683-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FV9yg1NBoB0HDHj681gSk%2Fuploads%2FAahr3f7W0ZLtCl04CAXW%2Fimagen.png?alt=media&#x26;token=63888ece-a5f3-4757-adac-4e5b75e4ee3d" alt=""><figcaption></figcaption></figure>
