Hardware & Memory Foundations

Concurrency vs Parallelism and JMM (Stack vs Heap)

Concurrency is dealing with multiple things via time-slicing. Parallelism is doing multiple things at once on physical cores. In JMM each thread has a private Stack, sharing the common Heap.

Processor (Hardware)
CPU Core 0
L1 / L2 Cache
Thread-1 (Running)
CPU Core 1
L1 / L2 Cache
Idle (1 Core Mode)
JVM Memory (Java Memory Model)
Stack Thread-1
int x = 10;
ref -> 0x4F10
Shared Heap
Objeto en 0x4F10 class Contador { count = 42; }
⚠️ Critical Conflict Zone
Stack Thread-2
int y = 99;
ref -> 0x4F10
Concurrency Hazards

Anatomy of a Race Condition: count++

count++ looks like a single statement but in bytecode comprises 3 non-atomic steps: ILOAD (read), IADD (add) and ISTORE (write).

T0: Variable count = 5 in shared memory
Hilo 1 (Thread-1)
1. ILOAD count (Lee 5 a registro local)
2. IADD 1 (Calcula 5 + 1 = 6)
3. ISTORE count (Escribe 6 en Heap)
Heap Value 5
Expected: 7 ...
Hilo 2 (Thread-2)
1. ILOAD count (¡Lee 5 antes de que H1 escriba!)
2. IADD 1 (Calcula 5 + 1 = 6)
3. ISTORE count (Sobrescribe con 6)
Synchronization Mechanisms

Intrinsic Lock (synchronized) vs Hardware Atomics (CAS)

synchronized parks threads using OS monitor locks (heavy). AtomicInteger relies on CPU Compare-And-Swap instructions without blocking (lock-free).

synchronized (Lock Pesado) Exclusión Mutua

One thread acquires the object monitor lock. Competing threads enter BLOCKED state waiting for release.

Hilo 1 (Dentro) Hilo 2 (BLOCKED)
public synchronized void incrementar() {
    count++; // Protegido por Monitor
}
AtomicInteger (CAS Lock-Free) Hardware CPU

Compares expected value against memory. If matched, swaps atomically in 1 hardware cycle; otherwise retries without parking.

CAS Loop 1 Ciclo CPU
private AtomicInteger count = new AtomicInteger();
// Sin locks: lock-free hardware atomic
count.incrementAndGet();
Mutual Block

The Danger of Deadlock and Prevention Rules

A Deadlock occurs when two or more threads freeze permanently waiting for resources held by each other. Prevented by enforcing strict canonical lock ordering.

Hilo A Hilo B Lock 1 Lock 2 Holds Waits Holds Waits
Circular Wait Condition: Thread A won’t release Lock 1 until getting Lock 2; Thread B won’t release Lock 2 until getting Lock 1. Permanent application freeze.
Java 21 Revolution

From Platform Threads to Pools and Virtual Threads (Project Loom)

A classic OS platform thread costs ~1 MB stack and heavy kernel overhead. Java 21 Virtual Threads are lightweight (~1 KB) managed purely by the JVM.

Traditional OS Threads
10.000 Threads: ~10 GB RAM (OutOfMemoryError)

1 Java Thread = 1 heavyweight OS kernel thread. Blocking in I/O stalls native thread.

Virtual Threads (Project Loom)
10.000 Threads: ~15 MB RAM (¡Ultraligero!)

Millions of virtual threads mounted onto few carrier threads. On I/O block, it unmounts cleanly.

Java 21+ Syntax
// 1 millón de hilos concurrentes sin colapsar la máquina:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(1000); // Se desmonta de la CPU durante el sleep
            return i;
        });
    });
} // AutoCloseable espera a que todos terminen