Junior — Middle
What is a deadlock when using goroutines and how can it be avoided?
sobes.tech AI
Answer from AI
A deadlock in the context of goroutines is a situation where two or more goroutines block each other forever, waiting for resources held by each other. For example, if goroutine A waits for a resource held by goroutine B, and goroutine B waits for a resource held by goroutine A, a deadlock occurs.
In Go, this can manifest when channels or mutexes are used improperly. For instance, if a goroutine tries to send data to a channel but no one is reading from it, or if multiple goroutines attempt to acquire mutexes in different orders.
How to avoid deadlocks:
- Avoid cyclic dependencies when acquiring multiple mutexes — always acquire them in the same order.
- Use buffered channels to prevent blocking during send operations when appropriate.
- Apply timeouts and contexts (context.Context) to cancel operations if waiting is prolonged.
- Minimize blocking operations and design architecture so that goroutines do not depend on each other directly.
Example of a simple deadlock situation with channels:
ch := make(chan int)
func main() {
go func() {
ch <- 1 // blocks because no one is reading
}()
// main does not read from ch, goroutine is forever blocked
}
To avoid this, read from the channel:
ch := make(chan int)
func main() {
go func() {
ch <- 1
}()
val := <-ch // reading unblocks the goroutine
fmt.Println(val)
}