Concurrent Programming
Concurrent programming writes code that correctly executes multiple tasks whose operations overlap in time. It addresses thread management, locks, atomic operations, message passing, and the patterns that prevent data races and deadlocks in shared-memory and distributed systems.
itSoftware engineering | OpenSkills.info
Intro
Concurrent Programming
Concurrent programming lets a program make progress on more than one task during the same period. The tasks may alternate on one processor core or run at the same instant on several cores. That distinction matters: concurrency is about structure, while parallelism is about simultaneous execution.
You use concurrency whenever work can overlap. A server handles one request while another waits for storage. A desktop application keeps its interface responsive during a download. A data pipeline processes independent partitions at once. The goal may be responsiveness, throughput, resource use, or a clear model for many activities in flight.
Concurrency also removes a useful assumption. In sequential code, one operation finishes before the next begins. In concurrent code, a scheduler may interleave operations in many valid orders. Your design must remain correct across every allowed order, not only the order you happened to observe in a test.
The execution building blocks
A process is a running program with its own resources and address space. A thread is a flow of control inside a process. Threads in one process normally share memory. A task is a unit of work submitted to a runtime or executor; the runtime decides which thread or process runs it. A coroutine is a function that can suspend and later resume, often on the same thread as other coroutines.
These abstractions solve different problems:
- Threads support preemptive concurrency and shared memory.
- Processes isolate memory and failures more strongly, but communication costs more.
- Tasks separate the work you want done from the workers that execute it.
- Coroutines make large numbers of waiting operations practical through cooperative suspension.
Continue the course
This section is part of the paid course.
See pricing to subscribe, or log in if you already have access.
Where this skill leads
Relevant careers
See how this topic contributes to broader role-level skill maps.
Sources
- https://go.dev/ref/mem
Supports
- Data races as conflicting accesses unordered by happens-before
- Happens-before as the transitive ordering built from program sequencing and synchronization
- Synchronization effects of goroutine creation, channels, mutexes, once, and atomic operations
- Data-race-free execution and sequential consistency
- https://docs.oracle.com/javase/specs/jls/se26/html/jls-17.html
Supports
- Monitor locking and unlocking
- Wait sets, notification, interruption, and thread joins
- Synchronization order, synchronizes-with edges, and happens-before
- Data-race definition and allowed execution behavior
- https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html
Supports
- Compound steps inside an increment or decrement
- Lost updates caused by interleaved read-modify-write operations
- Timing-dependent nature of thread-interference defects
- https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html
Supports
- Memory visibility between threads
- Happens-before effects of thread start and join
- https://docs.oracle.com/javase/tutorial/essential/concurrency/liveness.html
Supports
- Liveness as timely execution
- Deadlock, starvation, and livelock as liveness problems
- https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Supports
- Deadlock as threads blocked forever while waiting for one another
- Circular lock dependency example
- https://doc.rust-lang.org/book/ch16-02-message-passing.html
Supports
- Channels for communication between threads
- Multiple producers and transferred values
- Ownership constraints after sending a value
- https://doc.rust-lang.org/book/ch16-03-shared-state.html
Supports
- Shared-memory concurrency and multiple ownership
- Mutex-protected access
- Atomic reference counting for shared ownership across threads
- https://docs.python.org/3/library/concurrent.futures.html
Supports
- Executors as a high-level interface for asynchronous callable execution
- Threads, processes, and interpreters behind a shared executor interface
- Futures as handles for submitted execution
- Executor shutdown and cancellation behavior
- Deadlock when pool tasks wait cyclically or exhaust available workers
- https://docs.python.org/3/library/asyncio-task.html
Supports
- Coroutines, tasks, task groups, cancellation, and timeouts
- Task groups as structured concurrency scopes
- Child failure propagation, sibling cancellation, and cleanup before scope exit
- https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html
Supports
- Mutex acquire and release memory synchronization
- Condition wait release and reacquisition behavior
- Semaphore count and blocking behavior
- Data races and memory-order concepts in POSIX.1-2024
- https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_wait.html
Supports
- Atomic release and reacquisition of the associated mutex during a condition wait
- Re-evaluation of the predicate after return
