Java Concurrency Review
Reviews Java code for thread safety, race conditions, deadlocks, and Java 21 virtual thread compatibility. Use when user asks to "review concurrency", "is this thread safe", "check for race conditions", "concurrency issues", or "virtual thread compatible".
Review the Java code for concurrency correctness. Before reviewing, detect the Java version from pom.xml or build.gradle — suggest modern alternatives only if the version supports them.
Step 1 — Identify concurrency primitives in use
List all concurrency mechanisms found: synchronized, volatile, AtomicXxx, Lock, ExecutorService, CompletableFuture, CountDownLatch, Semaphore, BlockingQueue, virtual threads (Java 21+).
Step 2 — Review for race conditions
- Flag shared mutable fields accessed from multiple threads without synchronization
- Flag read-modify-write operations (e.g.,
count++) not wrapped insynchronizedorAtomicInteger - Flag non-atomic check-then-act patterns:
if (map.containsKey(k)) map.get(k)→ suggestmap.computeIfAbsent() - Flag
HashMapshared across threads → suggestConcurrentHashMap - Flag
ArrayList/HashSetshared across threads → suggest concurrent alternatives
Step 3 — Review for deadlocks
- Flag multiple locks acquired in inconsistent order across methods
- Flag
synchronizedcalls that invoke external/unknown code while holding a lock - Flag
ReentrantLockwithouttry/finallyunlock → lock may never be released - Flag nested
synchronizedblocks on different objects
Step 4 — Review synchronization granularity
- Flag
synchronizedon entire methods where only a small critical section needs protection - Suggest
ReentrantLockfor fine-grained locking with timeout capability - Flag
synchronized(this)in classes exposed to external code → suggest private lock object - For Java 21+: flag
synchronizedon virtual thread code → suggestReentrantLock(avoids carrier thread pinning)
Step 5 — Review visibility
- Flag fields shared across threads without
volatile,AtomicXxx, or synchronization - Flag
booleanflag fields used to stop threads → must bevolatileorAtomicBoolean - Flag lazy initialization without double-checked locking or
volatile
Step 6 — Review thread lifecycle
- Flag
new Thread(...)created directly in application code → suggestExecutorService - Flag
ExecutorServicenever shut down → resource leak - Flag unbounded thread pools (
Executors.newCachedThreadPool()) under high load → suggest bounded pool - For Java 21+: suggest
Executors.newVirtualThreadPerTaskExecutor()for I/O-bound workloads
Output format
- Summary — overall thread safety assessment
- Issues — grouped by: 🔴 Critical (data corruption risk) / 🟡 Warning (potential deadlock/liveness) / 🔵 Suggestion (improvement)
- Each issue: location + problem + fix with before/after code
Next Steps
- If deadlock risk found → suggest running thread dump analysis:
jstack <pid> - If using Java 21+ → consider
/java-virtual-threadsmodernization - After fixes → run
/java-reviewfor general code quality