Module 22 Systems

Concurrency & Parallelism

Concurrency bugs are the most insidious class of bugs in software engineering. They're intermittent — they appear under specific timing conditions that are hard to reproduce. They're sensitive to load — they hide in development and surface in production. They're often silent — a race condition that corrupts data may not produce an error message, just wrong results. If you've only written single-threaded code, you have no idea how bad it gets. This module doesn't shy away from the hard parts. You'll understand the difference between concurrency (managing multiple tasks) and parallelism (executing multiple tasks simultaneously), and why the distinction matters. You'll understand threads at the OS level — how they're scheduled, what context switching costs, why locks are necessary and where they fail. You'll implement the synchronization primitives yourself — mutexes, semaphores, condition variables — to understand what they actually do. You'll study race conditions and deadlocks not just to avoid them but to recognize them in code you didn't write. You'll learn lock-free programming with atomic operations and compare-and-swap. And you'll implement practical concurrent patterns: worker pools, connection pools, job queues — the patterns that power every high-performance server application. The web crawler project puts all of this together in a system that must be concurrent, bounded, and correct.

What You'll Learn

  • 1
    Concurrency vs Parallelism — The distinction that changes everything
  • 2
    Threads and Processes — OS threads, green threads, and the cost of context switching
  • 3
    Race Conditions — What they are, how they happen, and how to find them
  • 4
    Locks, Mutexes, and Semaphores — Synchronization primitives and their tradeoffs
  • 5
    Deadlocks and Livelocks — Detection, prevention, and avoidance strategies
  • 6
    Lock-Free Data Structures and Atomic Operations — CAS, memory ordering, practical patterns
  • 7
    Async Concurrency Models — Event loops, actor model, CSP, and goroutines
  • 8
    Concurrent Programming in Practice — Worker pools, connection pools, job queues

Capstone Project: Build a Concurrent Web Crawler with Worker Pools and Rate Limiting

Build a concurrent web crawler with a configurable worker pool — using channels for work distribution, a shared visited-URL set protected by a mutex, per-domain rate limiting with token buckets, depth limiting, and graceful shutdown that drains the queue cleanly. The crawler must never deadlock, never corrupt the visited set under concurrent access, and respect rate limits across concurrent workers hitting the same domain.

Why This Matters for Your Career

The free lunch is over. CPUs are no longer getting faster — they're getting more cores. Applications that can't use multiple cores are leaving performance on the table. Understanding concurrency is what allows engineers to write code that actually utilizes the hardware available, rather than running single-threaded workloads on 16-core machines. Server-side concurrency — handling multiple requests simultaneously — is the fundamental requirement for any production web service. Understanding thread pools, connection pools, and async I/O is what allows you to reason about server capacity, configure worker counts correctly, and diagnose the tail latency issues that plague badly configured concurrent systems. Race conditions and deadlocks in production systems can cause data corruption, service outages, and security vulnerabilities. Engineers who can audit concurrent code for these issues, design thread-safe data structures, and choose the appropriate synchronization primitive for a given problem are consistently more valuable in systems programming, backend development, and any domain where performance matters.