Concurrencia y multihilo en Go: nivel avanzado

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Concurrencia y multihilo en Go: nivel avanzado

\n\n

La concurrencia (concurrency) es una de las características clave del lenguaje Go, integrada en su arquitectura a nivel de runtime y sintaxis. A diferencia de muchos otros lenguajes, donde el multihilo se implementa mediante bibliotecas complejas y requiere gestión manual de hilos, Go ofrece gorutinas (goroutines) ligeras y canales (channels). A nivel avanzado, no basta con ejecutar varias tareas, sino que es necesario sincronizarlas correctamente, evitar condiciones de carrera y utilizar eficientemente los recursos del sistema. En este artículo, analizaremos técnicas avanzadas para trabajar con concurrencia en Go.

\n\n

1. Gorutinas: gestión del ciclo de vida y prioridades

\n\n

Las gorutinas son hilos ligeros gestionados por el runtime de Go. Se inician con la palabra clave go. Sin embargo, a nivel avanzado es necesario comprender cómo controlar su ejecución y finalización.

\n\n

Inicio básico de una gorutina:

\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc worker(id int) {\n    fmt.Printf("Worker %d starting\\n", id)\n    time.Sleep(time.Second)\n    fmt.Printf("Worker %d done\\n", id)\n}\n\nfunc main() {\n    for i := 1; i <= 5; i++ {\n        go worker(i)\n    }\n    time.Sleep(2 * time.Second) // Muleta: esperamos a que termine\n}
\n\n

Problema: en este ejemplo usamos time.Sleep para esperar, lo cual no es fiable. A nivel avanzado se utilizan canales y sync.WaitGroup.

\n\n

2. Sincronización con sync.WaitGroup

\n\n

sync.WaitGroup permite esperar a que finalice un número determinado de gorutinas. Es una herramienta básica pero potente para la sincronización.

\n\n
package main\n\nimport (\n    "fmt"\n    "sync"\n    "time"\n)\n\nfunc worker(id int, wg *sync.WaitGroup) {\n    defer wg.Done() // Disminuimos el contador al finalizar\n    fmt.Printf("Worker %d starting\\n", id)\n    time.Sleep(time.Second)\n    fmt.Printf("Worker %d done\\n", id)\n}\n\nfunc main() {\n    var wg sync.WaitGroup\n    for i := 1; i <= 5; i++ {\n        wg.Add(1) // Aumentamos el contador antes de iniciar\n        go worker(i, &wg)\n    }\n    wg.Wait() // Bloqueamos hasta que el contador llegue a cero\n    fmt.Println("All workers completed")\n}
\n\n

Importante: wg.Add() debe llamarse antes de iniciar la gorutina, de lo contrario podría haber una condición de carrera. Use defer wg.Done() dentro de la gorutina para garantizar la disminución del contador incluso en caso de pánico.

\n\n

3. Canales: buffering, dirección y select

\n\n

Los canales son el mecanismo principal para intercambiar datos entre gorutinas. A nivel avanzado se utilizan canales con buffer, canales unidireccionales y el operador select.

\n\n

3.1. Canales con buffer

\n

Los canales con buffer permiten enviar datos sin necesidad de recibirlos inmediatamente. Esto reduce los bloqueos y aumenta el rendimiento.

\n
package main\n\nimport "fmt"\n\nfunc main() {\n    ch := make(chan int, 3) // canal con buffer de 3 elementos\n    ch <- 1\n    ch <- 2\n    ch <- 3\n    // ch <- 4 // bloqueo, ya que el buffer está lleno\n    fmt.Println(<-ch)\n    fmt.Println(<-ch)\n    fmt.Println(<-ch)\n}
\n\n

3.2. Canales unidireccionales

\n

Para la seguridad de tipos y para indicar explícitamente el rol del canal, se utilizan canales unidireccionales: chan<- (solo envío) y <-chan (solo recepción).

\n
package main\n\nimport "fmt"\n\nfunc sender(out chan<- int) {\n    for i := 0; i < 5; i++ {\n        out <- i\n    }\n    close(out)\n}\n\nfunc receiver(in <-chan int) {\n    for val := range in {\n        fmt.Println(val)\n    }\n}\n\nfunc main() {\n    ch := make(chan int)\n    go sender(ch)\n    receiver(ch)\n}
\n\n

3.3. Operador select

\n

select permite que una gorutina espere en múltiples canales simultáneamente. Esto

Blogs

Book Recommendations