Concurrency and Parallelism
Concurrency and Parallelism are approaches in software design that allow programs to perform multiple operations at the same time, improving efficiency, responsiveness, and performance.
Concurrency
-
Definition: The ability of a system to handle multiple tasks at once by interleaving their execution (not necessarily at the exact same time).
-
Key Idea: Multiple tasks make progress independently and may share resources.
-
Example: A web server handling multiple client requests by switching between them quickly.
Parallelism
-
Definition: The simultaneous execution of multiple tasks to speed up computation.
-
Key Idea: Tasks run at the same time on multiple processors/cores.
-
Example: Performing large-scale matrix multiplication by dividing work across CPU cores or GPUs.
Concurrency vs. Parallelism
| Aspect |
Concurrency |
Parallelism |
| Focus |
Managing multiple tasks at once |
Executing multiple tasks simultaneously |
| Hardware Need |
Can run on a single core (task switching) |
Requires multiple cores/processors |
| Example |
Multithreaded UI app (smooth scrolling + typing) |
Scientific computing, GPU acceleration |
Techniques for Concurrency & Parallelism
-
Multithreading – Multiple threads within a program share resources.
-
Multiprocessing – Using multiple CPU processes for true parallel execution.
-
Asynchronous Programming – Non-blocking execution (e.g., async/await in Python or JavaScript).
-
Distributed Computing – Running tasks across multiple machines (e.g., cloud computing, Hadoop, Spark).
Example in Python (Concurrency vs Parallelism):
import threading, multiprocessing, time
def task(name):
print(f"Task {name} starting")
time.sleep(2)
print(f"Task {name} done")
# Concurrency (Threads: share same memory, switch tasks)
threads = [threading.Thread(target=task, args=(i,)) for i in range(2)]
for t in threads: t.start()
for t in threads: t.join()
# Parallelism (Processes: run in parallel on multiple cores)
processes = [multiprocessing.Process(target=task, args=(i,)) for i in range(2)]
for p in processes: p.start()
for p in processes: p.join()
Benefits
-
Better performance on multi-core systems.
-
Improved responsiveness (e.g., apps don’t freeze during heavy tasks).
-
Faster processing for large-scale data and computations.