[{"data":1,"prerenderedAt":190},["ShallowReactive",2],{"topic-java-concurrency":3},{"framework":4,"topic":15,"subtopics":24},{"id":5,"description":6,"extension":7,"icon":8,"meta":9,"name":10,"order":11,"slug":8,"stem":12,"tier":13,"__hash__":14},"frameworks\u002Fframeworks\u002Fjava.yml","Java interview questions on language fundamentals, object-oriented design, the Collections Framework, exception handling and concurrency — a staple of backend and enterprise technical interviews.","yml","java",{},"Java",5,"frameworks\u002Fjava",1,"jcUKEcQDoMZrreMRtZYJIVpkQlB-varlzbuwmzLr7kc",{"id":16,"description":17,"extension":7,"frameworkSlug":8,"meta":18,"name":19,"order":20,"slug":21,"stem":22,"__hash__":23},"topics\u002Ftopics\u002Fjava-concurrency.yml","Threads, synchronization, the memory model, executors and the high-level concurrency utilities used to write correct multithreaded Java.",{},"Concurrency",4,"concurrency","topics\u002Fjava-concurrency","m3PKd0A4OZd-vv3VInNyqKEXxsh5992rebNBGM1GqsM",[25],{"id":26,"title":27,"body":28,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":37,"navigation":38,"order":13,"path":39,"questions":40,"related":183,"seo":184,"seoDescription":185,"stem":186,"subtopic":187,"topic":19,"topicSlug":21,"updated":188,"__hash__":189},"qa\u002Fjava\u002Fconcurrency\u002Fthreads.md","Threads",{"type":29,"value":30,"toc":31},"minimark",[],{"title":32,"searchDepth":33,"depth":33,"links":34},"",2,[],"hard","md",{},true,"\u002Fjava\u002Fconcurrency\u002Fthreads",[41,46,50,55,59,63,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179],{"id":42,"difficulty":43,"q":44,"a":45},"thread-vs-runnable","easy","What are the ways to create a thread in Java?","Two basic approaches, plus the modern preferred one:\n\n- **Extend `Thread`** and override `run()` — simple, but uses up your single\n  inheritance slot.\n- **Implement `Runnable`** and pass it to a `Thread` — favored, because it\n  separates the task from the thread and works with executors.\n\n```java\n\u002F\u002F Runnable (preferred)\nRunnable task = () -> System.out.println(\"working\");\nnew Thread(task).start();\n\n\u002F\u002F extending Thread\nclass Worker extends Thread { public void run() { } }\n```\n\nIn real code you rarely create threads directly at all — you submit\n`Runnable`\u002F`Callable` tasks to an **`ExecutorService`**, which manages a pool\nfor you.\n",{"id":47,"difficulty":43,"q":48,"a":49},"start-vs-run","What is the difference between start() and run()?","**`start()`** asks the JVM to create a **new thread** and invoke `run()` on it —\nconcurrent execution. Calling **`run()`** directly just executes the method on\nthe **current** thread, like any ordinary call — no concurrency at all.\n\n```java\nThread t = new Thread(() -> System.out.println(Thread.currentThread().getName()));\nt.start();   \u002F\u002F prints \"Thread-0\" — runs on a new thread\nt.run();     \u002F\u002F prints \"main\"    — runs on the caller's thread\n```\n\nAlso, calling `start()` **twice** on the same `Thread` throws\n`IllegalThreadStateException` — a thread can be started only once.\n",{"id":51,"difficulty":52,"q":53,"a":54},"thread-lifecycle","medium","What are the states in a thread's lifecycle?","A `Thread` moves through these `Thread.State` values:\n\n- **NEW** — created but not started.\n- **RUNNABLE** — eligible to run (running or waiting for CPU).\n- **BLOCKED** — waiting to acquire a monitor lock.\n- **WAITING** — waiting indefinitely (`wait()`, `join()`, `park()`).\n- **TIMED_WAITING** — waiting with a timeout (`sleep`, `wait(ms)`).\n- **TERMINATED** — finished or threw.\n\n```java\nThread t = new Thread(task);\nt.getState();  \u002F\u002F NEW\nt.start();\nt.getState();  \u002F\u002F RUNNABLE\n```\n\nTransitions are driven by the scheduler and synchronization calls; you observe\n(not directly set) the state.\n",{"id":56,"difficulty":52,"q":57,"a":58},"race-condition","What is a race condition?","A race condition occurs when **multiple threads access shared mutable state\nconcurrently** and the outcome depends on the **timing** of their interleaving.\nOperations that look atomic (like `count++`) are actually read-modify-write\nsequences that can interleave and lose updates.\n\n```java\nclass Counter {\n  int count;\n  void inc() { count++; } \u002F\u002F read, +1, write — NOT atomic\n}\n\u002F\u002F 1000 threads each calling inc() once -> final count often \u003C 1000\n```\n\nFixes: make the operation atomic (`synchronized`, `AtomicInteger`), or avoid\nshared mutable state. Race conditions are insidious because they're\n**intermittent** and timing-dependent.\n",{"id":60,"difficulty":52,"q":61,"a":62},"synchronized","What does the synchronized keyword do?","`synchronized` enforces **mutual exclusion**: only one thread can hold an\nobject's **monitor lock** at a time, so synchronized code runs serially. It also\nestablishes a **happens-before** relationship, guaranteeing memory visibility of\nchanges made under the lock.\n\n```java\nclass Counter {\n  private int count;\n  synchronized void inc() { count++; }      \u002F\u002F locks on `this`\n  void dec() {\n    synchronized (this) { count--; }        \u002F\u002F synchronized block\n  }\n}\n```\n\nA `synchronized` instance method locks on `this`; a `synchronized` static method\nlocks on the **`Class`** object. Keep critical sections small to limit\ncontention.\n",{"id":64,"difficulty":35,"q":65,"a":66},"volatile","What does volatile do and what does it not do?","`volatile` guarantees **visibility** and **ordering**: writes by one thread are\nimmediately visible to others (no per-thread caching), and it prevents\nreordering around the access. What it does **not** provide is **atomicity** for\ncompound operations.\n\n```java\nvolatile boolean running = true;  \u002F\u002F flag — visibility is enough\nvoid stop() { running = false; }  \u002F\u002F other threads see this promptly\n\nvolatile int count;\ncount++;   \u002F\u002F still a race — read-modify-write isn't atomic\n```\n\nUse `volatile` for **flags\u002Fstate published once** (the classic stop-flag), and\n`synchronized`\u002F`Atomic*` when you need atomic compound updates.\n",{"id":68,"difficulty":35,"q":69,"a":70},"synchronized-vs-volatile","What is the difference between synchronized and volatile?","- **`volatile`** — only **visibility + ordering** for a single variable. No\n  locking, no atomicity for compound ops. Cheap.\n- **`synchronized`** — **mutual exclusion + visibility**. Makes whole code\n  blocks atomic, can guard multiple variables, but threads can block on the\n  lock.\n\n```java\nvolatile boolean flag;       \u002F\u002F visibility only\nsynchronized void transfer() {  \u002F\u002F atomicity across several fields\n  from -= amt; to += amt;\n}\n```\n\nQuick rule: a single flag\u002Freference written-then-read -> `volatile`; a\nmulti-step invariant or counter -> `synchronized` (or an atomic\u002Flock).\n",{"id":72,"difficulty":35,"q":73,"a":74},"deadlock","What is a deadlock and how do you prevent it?","A deadlock is two+ threads each **holding a lock the other needs**, so all wait\nforever. It requires four conditions (Coffman): mutual exclusion, hold-and-wait,\nno preemption, and circular wait.\n\n```java\n\u002F\u002F Thread 1: lock A then B   |   Thread 2: lock B then A  -> deadlock\nsynchronized (a) { synchronized (b) { } }\nsynchronized (b) { synchronized (a) { } }\n```\n\nPrevention: acquire locks in a **consistent global order**, use **timeouts**\n(`tryLock`), reduce lock scope, or avoid multiple locks entirely. Breaking any\none Coffman condition (usually circular wait, via lock ordering) prevents\ndeadlock.\n",{"id":76,"difficulty":35,"q":77,"a":78},"livelock-starvation","What are livelock and starvation?","- **Starvation** — a thread is perpetually denied the resources\u002FCPU it needs\n  (e.g. low-priority threads, or always losing a lock to greedier ones), so it\n  never makes progress.\n- **Livelock** — threads are **actively running** but keep responding to each\n  other in a way that prevents progress (like two people stepping aside in the\n  same direction repeatedly).\n\n```java\n\u002F\u002F livelock sketch: both threads keep \"politely\" backing off\nwhile (other.isActive()) { backOff(); \u002F* never proceeds *\u002F }\n```\n\nUnlike deadlock (threads blocked), livelocked threads consume CPU. Fixes\ninclude randomized back-off, fairness policies, and bounded retries.\n",{"id":80,"difficulty":35,"q":81,"a":82},"wait-notify","How do wait(), notify() and notifyAll() work?","They coordinate threads on an object's monitor and **must be called while\nholding that object's lock** (inside `synchronized`). `wait()` releases the lock\nand suspends the thread until notified; `notify()` wakes one waiter,\n`notifyAll()` wakes all.\n\n```java\nsynchronized (queue) {\n  while (queue.isEmpty()) {   \u002F\u002F ALWAYS loop, never a bare if\n    queue.wait();             \u002F\u002F releases lock, waits\n  }\n  process(queue.remove());\n}\n\u002F\u002F producer:\nsynchronized (queue) { queue.add(item); queue.notifyAll(); }\n```\n\nAlways re-check the condition in a **`while`** loop (spurious wakeups + stale\nconditions). Prefer `notifyAll` unless you're certain one waiter suffices.\n",{"id":84,"difficulty":52,"q":85,"a":86},"sleep-vs-wait","What is the difference between sleep() and wait()?","- **`Thread.sleep(ms)`** — a static method that pauses the **current** thread\n  for a time **without releasing any locks** it holds. For timing\u002Fthrottling.\n- **`Object.wait()`** — an instance method that **releases the object's lock**\n  and waits to be notified; must be called inside `synchronized`. For\n  coordination between threads.\n\n```java\nsynchronized (lock) {\n  Thread.sleep(100);  \u002F\u002F keeps holding `lock` the whole time\n  lock.wait();        \u002F\u002F releases `lock` while waiting\n}\n```\n\nKey distinction: `sleep` keeps the lock, `wait` gives it up. Using `sleep` for\ninter-thread coordination is a classic anti-pattern.\n",{"id":88,"difficulty":52,"q":89,"a":90},"executor-service","What is an ExecutorService and why use a thread pool?","An `ExecutorService` manages a **pool of reusable threads** and a task queue, so\nyou submit work instead of creating threads by hand. This caps the thread count,\nreuses threads (avoiding creation overhead), and decouples task submission from\nexecution.\n\n```java\nExecutorService pool = Executors.newFixedThreadPool(4);\nFuture\u003CInteger> f = pool.submit(() -> compute());\npool.execute(() -> fireAndForget());\npool.shutdown();                 \u002F\u002F stop accepting; finish queued tasks\npool.awaitTermination(1, TimeUnit.MINUTES);\n```\n\nCreating a thread per task doesn't scale — unbounded threads exhaust memory and\nthrash the scheduler. Always `shutdown()` a pool to release its threads.\n",{"id":92,"difficulty":52,"q":93,"a":94},"thread-pool-types","What thread pool types does Executors provide?","- **`newFixedThreadPool(n)`** — fixed number of threads, unbounded queue.\n- **`newCachedThreadPool()`** — grows\u002Fshrinks on demand; reuses idle threads.\n- **`newSingleThreadExecutor()`** — one thread, sequential task processing.\n- **`newScheduledThreadPool(n)`** — for delayed\u002Fperiodic tasks.\n- **`newVirtualThreadPerTaskExecutor()`** (Java 21) — a virtual thread per task.\n\n```java\nvar scheduled = Executors.newScheduledThreadPool(2);\nscheduled.scheduleAtFixedRate(this::poll, 0, 5, TimeUnit.SECONDS);\n```\n\nIn production many teams construct **`ThreadPoolExecutor`** directly to control\nthe queue bounds and rejection policy, since `newFixedThreadPool`'s unbounded\nqueue can hide backpressure problems.\n",{"id":96,"difficulty":52,"q":97,"a":98},"callable-future","What is the difference between Runnable and Callable, and what is a Future?","- **`Runnable`** — `run()` returns **nothing** and can't throw checked\n  exceptions.\n- **`Callable\u003CV>`** — `call()` **returns a value** and may throw checked\n  exceptions.\n- **`Future\u003CV>`** — a handle to a pending result; `get()` blocks until it's\n  ready, `isDone()`\u002F`cancel()` manage it.\n\n```java\nCallable\u003CInteger> task = () -> 6 * 7;\nFuture\u003CInteger> f = pool.submit(task);\nInteger result = f.get();   \u002F\u002F blocks until done -> 42\n```\n\n`Future.get()` is **blocking**, which is its main weakness — addressed by\n`CompletableFuture`'s non-blocking composition.\n",{"id":100,"difficulty":35,"q":101,"a":102},"completablefuture","What is CompletableFuture and how does it improve on Future?","`CompletableFuture` is a `Future` you can **compose and chain\nasynchronously** — attaching callbacks instead of blocking on `get()`, and\ncombining multiple async results.\n\n```java\nCompletableFuture.supplyAsync(() -> fetchUser(id))\n    .thenApply(User::name)                 \u002F\u002F transform when ready\n    .thenCompose(name -> lookupAsync(name)) \u002F\u002F chain another async call\n    .exceptionally(ex -> \"fallback\")        \u002F\u002F handle errors\n    .thenAccept(System.out::println);       \u002F\u002F consume, non-blocking\n\nCompletableFuture.allOf(f1, f2, f3).join();  \u002F\u002F wait for several\n```\n\nIt enables a non-blocking pipeline (`thenApply`\u002F`thenCompose`\u002F`thenCombine`),\nbuilt-in error handling, and easy fan-out\u002Ffan-in — far more flexible than the\nblocking `Future`.\n",{"id":104,"difficulty":52,"q":105,"a":106},"atomic-classes","What are the atomic classes and how do they work?","`java.util.concurrent.atomic` provides lock-free, thread-safe variables —\n`AtomicInteger`, `AtomicLong`, `AtomicReference`, etc. They use **CAS\n(compare-and-swap)** hardware instructions for atomic updates without locking.\n\n```java\nAtomicInteger count = new AtomicInteger();\ncount.incrementAndGet();          \u002F\u002F atomic ++\ncount.compareAndSet(5, 10);       \u002F\u002F set to 10 only if currently 5\nref.updateAndGet(v -> v + delta); \u002F\u002F atomic functional update\n```\n\nAtomics outperform `synchronized` for simple counters\u002Fflags under contention\n(no blocking), though heavy contention can cause CAS retry loops. For high\ncontention prefer `LongAdder`.\n",{"id":108,"difficulty":35,"q":109,"a":110},"cas","What is compare-and-swap (CAS)?","CAS is an atomic CPU instruction: \"if this memory location still holds the\n*expected* value, replace it with the *new* value, atomically; otherwise do\nnothing and report failure.\" It's the foundation of **lock-free** algorithms.\n\n```java\n\u002F\u002F typical lock-free retry loop\nint prev, next;\ndo {\n  prev = atomic.get();\n  next = prev + 1;\n} while (!atomic.compareAndSet(prev, next)); \u002F\u002F retry if another thread changed it\n```\n\nBecause no lock is held, there's no blocking or deadlock — but it can spin under\ncontention, and it has the **ABA problem** (a value changing A->B->A looks\nunchanged), which `AtomicStampedReference` solves with a version stamp.\n",{"id":112,"difficulty":35,"q":113,"a":114},"reentrantlock","What is ReentrantLock and how does it compare to synchronized?","`ReentrantLock` is an explicit lock with the same mutual-exclusion semantics as\n`synchronized` but **more features**: `tryLock()` (with timeout), interruptible\nlocking, **fairness** policy, and multiple **`Condition`** objects.\n\n```java\nReentrantLock lock = new ReentrantLock();\nlock.lock();\ntry { \u002F* critical section *\u002F }\nfinally { lock.unlock(); }   \u002F\u002F MUST unlock in finally\n\nif (lock.tryLock(1, TimeUnit.SECONDS)) { ... }  \u002F\u002F give up after 1s\n```\n\nTrade-off: `synchronized` is simpler and auto-releases on block exit;\n`ReentrantLock` is more powerful but you **must** `unlock()` in `finally` or you\nleak the lock. Use it only when you need its extra capabilities.\n",{"id":116,"difficulty":35,"q":117,"a":118},"read-write-lock","What is a ReadWriteLock?","A `ReadWriteLock` separates a **read lock** (shared — many readers at once) from\na **write lock** (exclusive). It boosts throughput for **read-heavy** data where\nwrites are rare, since concurrent reads don't block each other.\n\n```java\nReadWriteLock rw = new ReentrantReadWriteLock();\nrw.readLock().lock();   try { return cache.get(k); } finally { rw.readLock().unlock(); }\nrw.writeLock().lock();  try { cache.put(k, v); }     finally { rw.writeLock().unlock(); }\n```\n\nOnly one writer runs at a time and it excludes all readers. For very read-heavy\ncases, `StampedLock` (Java 8) adds optimistic reads that are even faster.\n",{"id":120,"difficulty":35,"q":121,"a":122},"threadlocal","What is ThreadLocal and when is it used?","`ThreadLocal\u003CT>` gives **each thread its own independent copy** of a variable,\nso there's no sharing and no synchronization needed. Common for per-thread\ncontext: `SimpleDateFormat` (not thread-safe), user\u002Frequest context, DB\nconnections.\n\n```java\nstatic final ThreadLocal\u003CSimpleDateFormat> FMT =\n    ThreadLocal.withInitial(() -> new SimpleDateFormat(\"yyyy-MM-dd\"));\nString today = FMT.get().format(new Date());  \u002F\u002F safe per-thread instance\n```\n\nCaution in **thread pools**: threads are reused, so you must **`remove()`** the\nvalue after use or it leaks into the next task (and can cause memory leaks).\n",{"id":124,"difficulty":35,"q":125,"a":126},"java-memory-model","What is the Java Memory Model and happens-before?","The Java Memory Model (JMM) defines **when writes by one thread become visible to\nanother** and what reorderings are allowed. The core concept is\n**happens-before**: if action A happens-before B, A's effects are guaranteed\nvisible to B.\n\nHappens-before edges include: program order within a thread; unlocking a monitor\n-> subsequent locking of it; a `volatile` write -> subsequent read; `Thread.start`\n-> the thread's actions; a thread's actions -> another's `join`.\n\n```java\nvolatile boolean ready;\nint data;\n\u002F\u002F Thread A:\ndata = 42; ready = true;          \u002F\u002F volatile write publishes `data`\n\u002F\u002F Thread B:\nif (ready) System.out.println(data); \u002F\u002F sees 42 — happens-before guarantees it\n```\n\nWithout a happens-before relationship, one thread may **never** see another's\nwrites (or see them reordered). This is *why* `volatile`\u002F`synchronized` matter.\n",{"id":128,"difficulty":52,"q":129,"a":130},"thread-safety","What does it mean for code to be thread-safe?","Thread-safe code behaves **correctly when accessed by multiple threads\nconcurrently**, without external synchronization, regardless of timing. You\nachieve it by: avoiding shared mutable state, **immutability**,\n**synchronization**, atomic variables, or thread-confinement (`ThreadLocal`).\n\n```java\n\u002F\u002F thread-safe by immutability — no state can change\nrecord Point(int x, int y) { }\n\u002F\u002F thread-safe by synchronization\nclass SafeCounter { private int n; synchronized void inc() { n++; } }\n```\n\nLevels range from **immutable** (always safe) -> **thread-safe** (handles its own\nsync) -> **conditionally safe** (some ops need external sync) -> **not\nthread-safe** (`ArrayList`, `HashMap`). The cheapest safety is having no shared\nmutable state at all.\n",{"id":132,"difficulty":35,"q":133,"a":134},"producer-consumer","How do you implement the producer-consumer pattern?","Producers add items to a shared buffer, consumers remove them; they must\ncoordinate so producers wait when full and consumers wait when empty. The\nidiomatic modern way is a **`BlockingQueue`**, which handles all the\nwaiting\u002Fnotifying internally.\n\n```java\nBlockingQueue\u003CTask> queue = new LinkedBlockingQueue\u003C>(100);\n\n\u002F\u002F producer\nqueue.put(task);        \u002F\u002F blocks if the queue is full\n\n\u002F\u002F consumer\nTask t = queue.take();  \u002F\u002F blocks if the queue is empty\n```\n\n`put`\u002F`take` block automatically — no manual `wait`\u002F`notify`. `ArrayBlockingQueue`\n(bounded) gives natural backpressure; `LinkedBlockingQueue` can be bounded or\nunbounded.\n",{"id":136,"difficulty":52,"q":137,"a":138},"countdownlatch","What are CountDownLatch and CyclicBarrier?","Both are synchronization aids that make threads wait for each other:\n\n- **`CountDownLatch`** — threads wait until a counter reaches zero; **one-shot**\n  (can't be reset). \"Wait for N tasks to finish.\"\n- **`CyclicBarrier`** — a fixed number of threads wait for **each other** at a\n  barrier point; **reusable** across rounds.\n\n```java\nCountDownLatch latch = new CountDownLatch(3);\nfor (int i = 0; i \u003C 3; i++)\n  pool.submit(() -> { work(); latch.countDown(); });\nlatch.await();   \u002F\u002F main thread blocks until all 3 finish\n```\n\n`CountDownLatch` is for \"main waits for workers\"; `CyclicBarrier` is for \"workers\nsync up repeatedly.\" `Semaphore` is a related tool that limits concurrent access\nto N permits.\n",{"id":140,"difficulty":52,"q":141,"a":142},"daemon-thread","What is a daemon thread?","A daemon thread is a **background thread that does not prevent the JVM from\nexiting**. The JVM shuts down once only daemon threads remain, abruptly stopping\nthem (their `finally` blocks may not run). Used for support tasks like GC,\nhousekeeping, and monitoring.\n\n```java\nThread t = new Thread(this::poll);\nt.setDaemon(true);   \u002F\u002F must be set BEFORE start()\nt.start();\n```\n\nUser (non-daemon) threads, by contrast, **keep the JVM alive** until they finish.\nSet the daemon flag before `start()` — changing it after throws\n`IllegalThreadStateException`. Don't use daemons for work that must complete.\n",{"id":144,"difficulty":35,"q":145,"a":146},"thread-interruption","How does thread interruption work?","Interruption is a **cooperative** signal, not a forced stop. `interrupt()` sets a\nthread's interrupt flag; the thread must **check it** (`isInterrupted()`) or be\nin a blocking call that throws `InterruptedException`. There is no safe way to\nforcibly kill a thread (`Thread.stop()` is deprecated and dangerous).\n\n```java\nwhile (!Thread.currentThread().isInterrupted()) {\n  try {\n    doWork();\n    Thread.sleep(100);\n  } catch (InterruptedException e) {\n    Thread.currentThread().interrupt(); \u002F\u002F restore the flag, then exit\n    break;\n  }\n}\n```\n\nBest practice: when you catch `InterruptedException` and can't propagate it,\n**restore the interrupt status** with `Thread.currentThread().interrupt()` so\ncallers still see it.\n",{"id":148,"difficulty":52,"q":149,"a":150},"synchronized-collections-conc","Why is ConcurrentHashMap preferred over synchronized maps?","`Collections.synchronizedMap` locks the **entire map** for every operation, so\nthreads serialize even on unrelated keys — a bottleneck. `ConcurrentHashMap`\nuses **fine-grained locking \u002F CAS on individual bins**, allowing many threads to\nread and write different buckets concurrently.\n\n```java\nMap\u003CString,Integer> m = new ConcurrentHashMap\u003C>();\nm.merge(word, 1, Integer::sum);     \u002F\u002F atomic compound update, no global lock\nm.computeIfAbsent(k, x -> load(x)); \u002F\u002F atomic\n```\n\nIt also offers **atomic** compound methods (`merge`, `computeIfAbsent`,\n`putIfAbsent`) and fail-safe iteration. The result is dramatically better\nthroughput under concurrency.\n",{"id":152,"difficulty":35,"q":153,"a":154},"false-sharing","What is false sharing?","False sharing is a performance problem (not a correctness bug) where two threads\nmodify **different variables that happen to sit on the same CPU cache line**.\nEach write **invalidates the whole line** in the other core's cache, forcing\nexpensive cache-coherence traffic even though the variables are independent.\n\n```java\n\u002F\u002F a[0] and a[1] may share a cache line; two threads hammering them contend\nlong[] counters = new long[2];\n\u002F\u002F padding or @Contended separates hot fields onto different lines\n```\n\nMitigations: pad hot fields apart, use `@jdk.internal.vm.annotation.Contended`,\nor use `LongAdder`, which internally stripes counters across cells to avoid\ncontention.\n",{"id":156,"difficulty":43,"q":157,"a":158},"thread-priority","How do thread priorities work?","Each thread has a priority from 1 (`MIN_PRIORITY`) to 10 (`MAX_PRIORITY`),\ndefault 5. It's only a **hint** to the OS scheduler about relative importance —\nnot a guarantee. Behavior is platform-dependent and often ignored.\n\n```java\nThread t = new Thread(task);\nt.setPriority(Thread.MAX_PRIORITY);  \u002F\u002F best-effort hint only\n```\n\nDon't build correctness on priorities — they can't ensure ordering and, on some\nplatforms, do almost nothing. For real coordination use explicit synchronization\nor executor configuration.\n",{"id":160,"difficulty":52,"q":161,"a":162},"synchronized-static","What is the difference between a synchronized instance method and a static one?","The difference is **which lock** is acquired:\n\n- A `synchronized` **instance** method locks on **`this`** (the object). Two\n  threads on *different instances* don't contend.\n- A `synchronized` **static** method locks on the **`Class`** object, shared by\n  all instances.\n\n```java\nclass C {\n  synchronized void a() { }          \u002F\u002F locks on this instance\n  static synchronized void b() { }   \u002F\u002F locks on C.class (one global lock)\n}\n```\n\nA subtle bug: `a()` and `b()` use **different locks**, so they can run\nsimultaneously even though both are \"synchronized.\" Mixing instance and static\nsynchronization on shared state doesn't protect it.\n",{"id":164,"difficulty":35,"q":165,"a":166},"double-checked-locking","What is double-checked locking and why does it need volatile?","Double-checked locking lazily initializes a singleton while only locking on the\nfirst call:\n\n```java\nclass Singleton {\n  private static volatile Singleton instance;   \u002F\u002F volatile is essential\n  static Singleton get() {\n    if (instance == null) {                      \u002F\u002F 1st check (no lock)\n      synchronized (Singleton.class) {\n        if (instance == null) {                  \u002F\u002F 2nd check (locked)\n          instance = new Singleton();\n        }\n      }\n    }\n    return instance;\n  }\n}\n```\n\nWithout **`volatile`**, another thread could see a **partially constructed**\nobject: `instance = new Singleton()` isn't atomic (allocate, construct, assign),\nand reordering could publish the reference before construction finishes.\n`volatile` forbids that reordering. (An enum or holder-class singleton avoids the\nwhole issue.)\n",{"id":168,"difficulty":35,"q":169,"a":170},"blocking-vs-nonblocking","What is the difference between blocking and non-blocking algorithms?","- **Blocking** algorithms use locks; a thread that can't proceed is **suspended**\n  (BLOCKED\u002FWAITING) until the lock frees. Simple, but a slow\u002Fdead lock-holder\n  stalls others (and risks deadlock).\n- **Non-blocking** (lock-free) algorithms use **CAS** retry loops; a thread never\n  suspends — it retries until it succeeds. No deadlock, better scalability, but\n  harder to write and can livelock\u002Fspin.\n\n```java\n\u002F\u002F non-blocking counter\nAtomicLong c = new AtomicLong();\nc.incrementAndGet();   \u002F\u002F CAS loop under the hood — never blocks\n```\n\n`java.util.concurrent` provides both: `ReentrantLock`\u002F`BlockingQueue` (blocking)\nand `Atomic*`\u002F`ConcurrentLinkedQueue` (non-blocking).\n",{"id":172,"difficulty":35,"q":173,"a":174},"virtual-threads","What are virtual threads (Project Loom)?","Virtual threads (Java 21) are **lightweight threads managed by the JVM**, not the\nOS. Millions can exist at once because a blocked virtual thread is **unmounted**\nfrom its carrier OS thread, freeing it for other work. This makes the simple\n\"thread-per-request\" blocking style scale like async code.\n\n```java\ntry (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n  for (var task : tasks) executor.submit(task); \u002F\u002F a virtual thread each\n}\n```\n\nThey're cheap to create and ideal for **I\u002FO-bound** workloads (many tasks\nblocking on network\u002FDB). For CPU-bound work, platform threads sized to the cores\nare still the right tool — virtual threads don't add CPU.\n",{"id":176,"difficulty":52,"q":177,"a":178},"synchronization-overhead","What is lock contention and how do you reduce it?","Lock contention occurs when many threads compete for the **same lock**, so they\nserialize and queue up — throughput collapses as cores sit idle waiting. The fix\nis to reduce how often and how long threads hold shared locks.\n\nStrategies:\n- **Shrink the critical section** — hold the lock for as little code as possible.\n- **Lock striping** — split one lock into many (what `ConcurrentHashMap` does).\n- **Use atomics \u002F lock-free** structures for simple state.\n- **Immutable or thread-local** data to avoid sharing.\n- **Read-write locks** when reads dominate.\n\n```java\n\u002F\u002F whole method locked     \u002F\u002F lock only the shared mutation\nsynchronized void m() {       void m() {\n  var x = expensive();          var x = expensive();\n  shared.add(x);                synchronized (shared) { shared.add(x); }\n}                             }\n```\n",{"id":180,"difficulty":52,"q":181,"a":182},"executor-shutdown","How do you properly shut down an ExecutorService?","Use the standard two-phase shutdown so in-flight tasks finish and threads are\nreleased (a pool's non-daemon threads otherwise keep the JVM alive):\n\n```java\npool.shutdown();                      \u002F\u002F stop accepting new tasks\ntry {\n  if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {\n    pool.shutdownNow();               \u002F\u002F interrupt running tasks\n    pool.awaitTermination(10, TimeUnit.SECONDS);\n  }\n} catch (InterruptedException e) {\n  pool.shutdownNow();\n  Thread.currentThread().interrupt();\n}\n```\n\n`shutdown()` is graceful (finish queued work); `shutdownNow()` interrupts active\ntasks and returns the unstarted ones. Forgetting to shut down a pool is a common\nresource\u002Fthread leak.\n",null,{"description":32},"Java concurrency interview questions — threads vs Runnable, synchronized, volatile, the memory model, deadlock, wait\u002Fnotify, executors, futures, CompletableFuture and atomic classes.","java\u002Fconcurrency\u002Fthreads","Threads & Synchronization","2026-06-18","bB9xo_QxZtFCRbhLK1eQaCAHZBmcvpo3dMNQY89_qMM",1781808674531]