What is Go routine(Thread)
-
A goroutine is a lightweight thread managed by the Go runtime.
Memory allocation on stack, heap is very less wrt OS Threads. Goroutine vs OS Threads
Code
Hello World
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello from goroutine!")
}
func main() {
go sayHello() // Start a goroutine
fmt.Println("Hello from main!") // Print from the main goroutine
// Sleep for a while to allow the goroutine to execute
time.Sleep(time.Second)
}
$ go run main.go
Hello from main!
Hello from goroutine!
10 Threads executing 1 function
| Code | Description |
|---|---|
|
sync.waitgroup: - Synchronization primitive provided by the Go to synchronize the execution of a group of goroutines. - How it works? A WaitGroup maintains shared counter internally(which is initially set to 0). counter is thread-safe. At start of goroutine wg.Add(numberOfWorkers) is called. This makes counter=10 goroutine finishes (defer make wg.Done() to called after function finishes), and counter is decremented wg.Wait() method in main waits until counter=0 defer - keyword in Go schedules a function call to be executed just before the surrounding function returns. - ie wg.Done() would be called when surrounding function finishes - defer wg.Done() is called reliably, even in case of errors or unexpected goroutine termination. |
Memory Leak in goroutine
-
Memory allocated to goroutine: Around
2k bytes of Stack
is allocated to goroutines by Go runtime at time of creation and this
memory grows/shrinks dynamically.
When goroutine dies then this memory is taken back by go runtime(ie no leak).
How leak happens in goroutine? Memory leak in goroutine means go runtime fails to cleanup the goroutine and hence fails to claim back this allocated memory(2k bytes or more).
Leak Condition:
- When no reciever is present on unbuffered channel, then that goroutine which is sending data on channel and channel are not Garbage collected by Go runtime.
- Memory allocated to goroutine + memory allocated to go channel is leaked.
---Unbufferd channel---
/\
|
goroutine sends data
-
How to avoid Memory leak? Use
buffered channel
Bounded go routines
-
By default, Go makes it easy to spawn thousands of goroutines.
And each goroutine consumes memory or network handles, spawning them without a limit (unbounded) can lead to Out of Memory (OOM) errors or CPU exhaustion.
Bounded goroutines ensure only a fixed number of goroutines run at once
We can implement bounded goroutines using 2 patterns:
1. Semaphore OR
2. Worker Pool
1. Semaphore based bounded goroutines
-
Use a
buffered channel
with limit on number of values it can hold.