Run concurrency problem demos
master./mvnw). Each demo is a standalone class that reproduces a specific concurrency issue (e.g., visibility issues, deadlocks, or race conditions).repository·master·Indexed 22 days ago
https://github.com/oldratlee/fucking-java-concurrencyA collection of Java demonstrations showcasing common concurrency pitfalls and bugs. The repository provides standalone classes to reproduce issues such as visibility problems, deadlocks, livelocks, race conditions, word tearing in long variables, and HashMap infinite loops, providing observable evidence of concurrency principles through code.
./mvnw). Each demo is a standalone class that reproduces a specific concurrency issue (e.g., visibility issues, deadlocks, or race conditions).This demo demonstrates visibility issues where a change made to a field in one thread is not visible to another thread because it lacks proper synchronization or volatile semantics.
Demo Class: fucking.concurrency.demo.NoPublishDemo
Scenario: The main thread sets a stop field to true, but the task thread continues to run indefinitely because it never sees the updated value.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.NoPublishDemoThe FinalInitialDemo demonstrates how instruction reordering can cause non-final field variables to be read incorrectly. In this scenario, a writer thread calls a class constructor, while a reader thread attempts to access the non-final member variables. If instruction reordering occurs, the non-final variables might be placed outside the constructor's scope from the perspective of other threads, causing the reader to see default initial values instead of the values set in the constructor. Note that this behavior depends on specific hardware and JVM environments.
Target class: fucking.concurrency.demo.FinalInitialDemo
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemoThe CyclicThreadPoolDeadLockDemo demonstrates a deadlock caused by cyclic dependencies between tasks in thread pools.
badCase): Two thread pools (pool1 and pool2) submit tasks to each other. When the threads in the pools are exhausted, all executing tasks wait for tasks that cannot start, resulting in a deadlock.goodCase): The deadlock is avoided by using asynchronous chained calls with CompletableFuture, which prevents blocking the thread pool threads.Target class: fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemoThis demo reproduces a classic deadlock scenario involving symmetric locks.
Demo Class: fucking.concurrency.demo.SymmetricLockDeadlockDemo
Scenario: Two task threads attempt to acquire locks in a way that results in a permanent deadlock.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SymmetricLockDeadlockDemoThis demo shows how concurrent increments without synchronization lead to lost updates and incorrect final counts.
Demo Class: fucking.concurrency.demo.WrongCounterDemo
Scenario: Two task threads execute concurrent increments, and the main thread verifies that the final count is less than expected.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.WrongCounterDemoThis demo shows how reading multiple related states (like fields in a POJO or multiple ints) without synchronization can result in an 'invalid combination'—a state that was never actually set by the writer.
Demo Class: fucking.concurrency.demo.InvalidCombinationStateDemo
Scenario: The main thread modifies two states where the second is always twice the first. The task thread reads them and finds a combination where this relationship does not hold.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidCombinationStateDemoThis demo reproduces the classic issue where concurrent modifications to a non-thread-safe HashMap can cause an infinite loop during a get operation.
Demo Class: fucking.concurrency.demo.HashMapHangDemo
Scenario: Two task threads perform put operations on a HashMap while the main thread performs a get operation, leading to a hang.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.HashMapHangDemoThis demo illustrates the danger of synchronizing on a field that is itself mutable, which can fail to provide the intended thread safety.
Demo Class: fucking.concurrency.demo.SynchronizationOnMutableFieldDemo
Scenario: Two task threads execute addListener. The final count of listeners is incorrect because the synchronization mechanism was misused.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SynchronizationOnMutableFieldDemoThis demo demonstrates a livelock, where threads are not blocked but are unable to make progress because they are constantly reacting to each other.
Demo Class: fucking.concurrency.demo.ReentrantLockLivelockDemo
Scenario: Two task threads try to acquire a lock held by the other. They repeatedly release their own lock and immediately re-acquire it, preventing the other thread from ever acquiring both locks.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.ReentrantLockLivelockDemoThis demo demonstrates that reading and writing 64-bit long variables is not atomic in Java and can be split into two 32-bit operations, leading to 'word tearing'.
Demo Class: fucking.concurrency.demo.InvalidLongDemo
Scenario: The main thread writes long values where the upper and lower 4 bytes are identical. The task thread reads a value where the upper and lower 4 bytes differ, representing a value that was never written.
./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidLongDemo