fucking-java-concurrency

repository·master·Indexed 22 days ago

https://github.com/oldratlee/fucking-java-concurrency

A 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.

Tokens
1.6K
Snippets
10
Records
11
Agent score
29%

What's inside fucking-java-concurrency

  1. Run concurrency problem demos

    master
    This repository provides showcases of common Java concurrency problems. You can run individual demos using the Maven wrapper (./mvnw). Each demo is a standalone class that reproduces a specific concurrency issue (e.g., visibility issues, deadlocks, or race conditions).
  2. Reproduce: Update without synchronization cannot be read in another thread

    master

    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.NoPublishDemo
  3. Run the FinalInitialDemo to observe instruction reordering errors

    master

    The 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.FinalInitialDemo
  4. Run the CyclicThreadPoolDeadLockDemo to observe thread pool deadlocks

    master

    The CyclicThreadPoolDeadLockDemo demonstrates a deadlock caused by cyclic dependencies between tasks in thread pools.

    • The Problem (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.
    • The Solution (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.CyclicThreadPoolDeadLockDemo
  5. Reproduce: Deadlock caused by symmetric locks

    master

    This 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.SymmetricLockDeadlockDemo
  6. Reproduce: Concurrency count without synchronization is wrong

    master

    This 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.WrongCounterDemo
  7. Reproduce: Combined state read invalid combination

    master

    This 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.InvalidCombinationStateDemo
  8. Reproduce: Infinite loop of `HashMap`

    master

    This 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.HashMapHangDemo
  9. Reproduce: Synchronization on mutable fields

    master

    This 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.SynchronizationOnMutableFieldDemo
  10. Reproduce: Livelock caused by reentrant locks

    master

    This 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.ReentrantLockLivelockDemo
  11. Reproduce: `long` variable read invalid value

    master

    This 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