Latest stories

[THREADING 101] the Series Overview

[

A comprehensive guide to multithreading and concurrency in Java, from fundamentals to advanced techniques. A great fit for engineers learning the basics of multi-threaded applications in theory and practice. Articles #TopicKey Concepts01 – Threading BasicsThread lifecycle, creation, interruption, poolsThread states, Runnable, ExecutorService, volatile02 – Race Conditions and Data...

[THREADING 101] 09 – Virtual Threads (Java 21+)

[

The Problem with Platform Threads Platform threads (the traditional Thread class) are thin wrappers around OS threads. Each one consumes: ~1 MB of stack memory Kernel resources for scheduling Expensive context switches (~1-10 μs) This means a typical server can sustain only thousands of platform threads before running out of memory or spending all its time context-switching. But modern servers...

[THREADING 101] 08 – Future

[

The Problem: Blocking for Results When you submit a task to a thread pool, you need a way to get the result. Without a placeholder, you’d have to block the calling thread until the work completes: // Without Future — calling thread is stuck until work finishes Result result = doExpensiveWork(); // Blocks here for 5 seconds useResult(result); Future and CompletableFuture solve this by giving...

[THREADING 101] 07 – Lock-Free Algorithms

[

What Does “Lock-Free” Mean? An algorithm is lock-free if at least one thread is guaranteed to make progress in a finite number of steps, regardless of what other threads are doing. If one thread crashes or gets paused by the OS, the remaining threads continue without being blocked. Compare this to lock-based code: if the thread holding a lock is suspended, every other thread waiting...

[THREADING 101] 06 – Atomic Classes and Operations

[

The Problem with Locks Locks work, but they have costs: Contention — threads waiting for a lock do nothing useful. Context switches — the OS moves blocked threads on and off the CPU. Priority inversion — a low-priority thread holding a lock blocks a high-priority thread. Deadlock risk — multiple locks can create circular dependencies. For simple operations — incrementing a counter, updating a...

[THREADING 101] 05 – Semaphores

[

What is a Semaphore? A semaphore is a concurrency primitive that controls access to a shared resource by maintaining a set of permits. Threads acquire permits before accessing the resource and release them when done. Unlike locks, semaphores don’t have an “owner” — any thread can release a permit, not just the one that acquired it. Key Difference: Semaphore vs Lock...

[THREADING 101] 04 – Locks and Conditions

[

Why Explicit Locks? The synchronized keyword handles most locking needs, but it has rigid semantics. The java.util.concurrent.locks package provides explicit lock implementations with richer capabilities: Try-lock — attempt to acquire without blocking forever Timed lock — give up after a timeout Interruptible lock — can be interrupted while waiting Fairness — first-come-first-served ordering...

[THREADING 101] 03 – Synchronization in Java

[

Why Synchronize? Synchronization solves both race conditions and data races by providing two guarantees: Mutual exclusion — Only one thread can execute the protected section at a time. Memory visibility — Changes made by a thread inside a synchronized block are visible to the next thread that enters the same synchronized block. The synchronized Keyword Synchronized Methods public class...

[THREADING 101] 02 – Race Conditions and Data Races

[

Overview When multiple threads access shared mutable state without proper coordination, two fundamental categories of bugs can occur: race conditions and data races. They are related but distinct problems. Race Condition A race condition occurs when the correctness of a program depends on the relative timing of thread execution. Multiple threads compete to read and write the same resource, and...

[Threading 101] 01 – Threading Basics

[

Threading Basics in Java What is a Thread? A thread is the smallest unit of execution within a process. Every Java application starts with a single thread — the main thread — and can spawn additional threads to perform work concurrently. A process owns memory, file handles, and other resources. Threads within the same process share that memory space, which makes communication between them fast...

Maksim

Get in touch

Reach out if you want to discuss engineering leadership, collaborate on something interesting, or suggest topics you'd like me to write about.