Basic Concurrency #Go Concurrency 1
Overview
First, when I’m learning about concurrency in Golang, the first thing I should understand is the definition of the concurrency itself, because in the backend context there are many terms that sound similar like asynchronous and parallelism. so I figured out the differences between them.
- Asynchronous handle multiple tasks without blocking, using a single thread
- Parallelism handle multiple tasks without blocking in multiple thread
- Concurrency is about handling multiple tasks at once, which can be achieved through various means (single-threaded async, multi-threading, etc.)
I am still confused between asynchronous and concurrency because these two terms sound very similar. so I was still curious until I developed this mental model: :
Concurrency is the broader concept - it's about dealing with multiple tasks at once, regardless of how you achieve it. Concurrency can be implemented through:
- Single-threaded (like async programming)
- Multi-threaded (like thread pools)
- Both achieve concurrency, but through different means
So concurrency is the "what" (handling multiple tasks), while async and parallelism are different "hows" to achieve it.
The Restaurant Analogy
Concurrency = "The restaurant can serve multiple customers at once" This is the goal - customers don't have to wait for one person to completely finish before the next person gets any service.
Now, there are different ways to achieve this concurrency:
Asynchronous (Single-threaded approach)
One super-efficient waiter handling multiple tables:
The waiter takes an order from Table 1, sends it to the kitchen, then immediately goes to Table 2 while Table 1's food is being prepared. While Table 2's order is cooking, they check on Table 3, refill drinks at Table 4, and bring out Table 1's ready food.
- One person (single thread)
- Multiple tasks happening simultaneously
- Non-blocking: Never standing around waiting, always doing something productive
.
Parallelism (Multi-threaded approach)
Multiple waiters working simultaneously:
Waiter A handles Tables 1-3, Waiter B handles Tables 4-6, Waiter C handles Tables 7-9. All three waiters are literally working at the same time on different customers.
- Multiple people (multiple threads)
- True simultaneous work
The Key Insight
Both restaurants achieve concurrency (serving multiple customers without one blocking another), but through completely different methods:
- Restaurant A uses async: One amazing multitasking waiter
- Restaurant B uses parallelism: Multiple waiters working together
Concurrency = "We can handle multiple customers efficiently" Async/Parallelism = "Here's HOW we handle multiple customers efficiently". Now that we understand concurrency concepts, let's see how Go implements them differently.
Why Does This Matter In Go?
Go follows a key principle “Do not communicate by sharing memory; instead, share memory by communicating.” reference : https://go.dev/doc/effective_go#concurrency
Instead of using a lock and unlock mechanism to access shared resources, Golang offers a “channel” mechanism to communicate between shared resources. Let’s move back to the restaurant analogy.
When we use lock and unlock mechanism, concurrent programming works like a chaotic restaurant where multiple waiters all share the same order pad, cash register, and customer database. All waiters have access to the same resources. But to prevent disasters (like two waiters taking the same order or processing the same payment), the restaurant must use strict rules and locks.
Imagine each waiter having to grab a key before using the cash register or order system. Only one waiter can use the locked resource at a time, while others stand around waiting their turn. Everyone's competing for the same shared tools.
When using the channel mechanism, instead of having waiters fight over shared resources, Go's restaurant operates more like a well-organized communication chain. Each waiter (goroutine) has their own designated role, and information flows between them through a clear messaging system (channels). When Waiter A takes an order, they pass it through the communication system to Waiter B who handles kitchen coordination, who then passes the ready notification to Waiter C for food delivery. At any given moment, only one waiter "owns" each piece of customer information or task.
The Next Section
We'll get hands-on with Go concurrency using goroutines and channels. Stay tuned!