Software Engineering basics - Concurrency and Parallelism
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.