Golang - Concurrency - Goroutines vs Threads
Publish date: 2025-09-27
Tags:
<a href="https://programmercave.com/tags/Go/">Go</a>
This is a fundamental concept in Go and a very common interview question. Understanding the difference shows you grasp why Go is so powerful for concurrent applications.
The Core Distinction: Who’s in Charge?
- OS Threads: Managed by the Operating System (OS). The OS kernel decides when to start, stop, and switch threads. It’s a heavyweight, system-level operation.
- Goroutines: Managed by the Go Runtime. The Go runtime has its own scheduler that runs inside your application. It’s a lightweight, application-level operation.
Analogy: The Restaurant
- OS Threads are like Chefs. Each chef is a powerful, independent worker. But hiring a new chef is a big deal (slow and expensive), and having too many chefs in the kitchen creates a lot of overhead and communication problems.
- Goroutines are like Kitchen Helpers. You can have dozens of helpers. They are cheap to “hire” (create), take up very little space (memory), and can switch between tasks (chopping, washing, plating) very quickly. A single chef (the Go scheduler) can efficiently manage all the helpers.
Key Differences at a Glance
Feature | Goroutines | OS Threads |
---|---|---|
Management | Go Runtime (in-app) | Operating System (kernel) |
Creation Cost | Very Low. Fast to create. | High. Slow to create. |
Memory (Stack Size) | Starts tiny (~2KB) and grows as needed. | Large and fixed (1-2MB). |
Context Switching | Very Fast. Happens within the Go process. | Slow. Requires the OS to intervene. |
Scalability | Massive. You can run hundreds of thousands. | Limited. You can only run a few thousand. |
Why Does This Matter?
The lightweight nature of goroutines is what makes Go so well-suited for modern, concurrent applications like:
- Web Servers: A web server can handle thousands of incoming connections simultaneously by giving each connection its own goroutine. This would be impossible with OS threads.
- Data Pipelines: You can create complex pipelines where data is processed in stages, with each stage running in its own goroutine.
- Concurrent APIs: Easily make multiple API calls at the same time and wait for all of them to complete.
The Go Scheduler: The “Chef” in the Kitchen
The Go runtime has a sophisticated scheduler that manages all the goroutines. It’s responsible for:
- Multiplexing: It takes all your goroutines (the “M” helpers) and runs them on a small number of OS threads (the “N” chefs). This is called an M:N scheduler.
- Work-Stealing: If one OS thread runs out of goroutines to execute, it can “steal” goroutines from other threads. This keeps all the CPU cores busy.
- Handling Blocking Calls: If a goroutine makes a blocking call (like reading from a file or a network connection), the scheduler will move it off the OS thread and let another goroutine run. This prevents the entire thread from being blocked.
Key Takeaways for Your Interview
- Goroutines are not threads. They are a higher-level abstraction.
- Goroutines are managed by the Go runtime, threads are managed by the OS.
- Goroutines are much more lightweight and scalable than threads. This is the primary reason Go is so good at concurrency.
- The Go runtime uses an M:N scheduler to efficiently run many goroutines on a few OS threads.
Tags:
<a href="https://programmercave.com/tags/Go/">Go</a>