### Usage Example for FinalInitialDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Demonstrates how to use the FinalInitialDemo class with two threads, one for writing and one for reading, to observe potential instruction reordering. ```java FinalInitialDemo demo = new FinalInitialDemo(); Thread threadA = new Thread(demo::writer); Thread threadB = new Thread(demo::reader); threadA.start(); threadB.start(); ``` -------------------------------- ### Starting Thread for Lock2-Lock1 Acquisition Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Launches a single thread to execute `ConcurrencyCheckTask2`. This is the second part of the deadlock demonstration setup. ```Java Thread thread2 = new Thread(new ConcurrencyCheckTask2()); thread2.start(); ``` -------------------------------- ### Java: Demonstrate NoPublishDemo Visibility Issue Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Starts a task thread and then attempts to signal it to stop by setting a 'stop' field. This example illustrates the potential visibility problem where the task thread might not see the updated 'stop' value. ```java NoPublishDemo demo = new NoPublishDemo(); Thread thread = new Thread(demo.getConcurrencyCheckTask()); thread.start(); Thread.sleep(1000); demo.stop = true; // Write by main thread // On unsynchronized/non-volatile field, task thread may not observe this change ``` -------------------------------- ### makeLoad() Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Creates and starts load-generating threads that consume CPU resources. Spawns CPU-intensive background tasks equal to twice the number of available processors. Each thread runs an infinite loop with periodic sleep intervals, allowing concurrent demonstrations to run under sustained CPU load. ```APIDOC ## makeLoad() ### Description Creates and starts load-generating threads that consume CPU resources. Spawns CPU-intensive background tasks equal to twice the number of available processors. Each thread runs an infinite loop with periodic sleep intervals, allowing concurrent demonstrations to run under sustained CPU load. Setting `isLoadMade` to `true` enables the load, and tasks monitor this flag to determine when to terminate. ### Method ```java public static synchronized void makeLoad() ``` ### Parameters None ### Return Type `void` ### Example ```java import fucking.concurrency.demo.util.LoadMaker; public class ConcurrencyTest { public static void main(String[] args) throws Exception { LoadMaker.makeLoad(); // Run your concurrency demo under sustained CPU load Thread.sleep(5000); LoadMaker.stopLoad(); } } ``` ``` -------------------------------- ### Starting Thread for Lock1-Lock2 Acquisition Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Launches a single thread to execute `ConcurrencyCheckTask1`. This is part of a deadlock demonstration setup. ```Java Thread thread1 = new Thread(new ConcurrencyCheckTask1()); thread1.start(); ``` -------------------------------- ### Execute Java Concurrency Demos with Maven Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/INDEX.md These commands use Maven to compile and run specific Java concurrency demo classes. Ensure you have Maven installed and the project is set up correctly. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.NoPublishDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.HashMapHangDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidCombinationStateDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidLongDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.WrongCounterDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SynchronizationOnMutableFieldDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SymmetricLockDeadlockDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.ReentrantLockLivelockDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InconsistentReadDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo ``` ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo good ``` -------------------------------- ### Troubleshoot 'Java not found' Error Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md If you encounter the 'Java not found' error, ensure you have Java 8+ JDK installed and that the 'java' command is accessible in your system's PATH. ```text [ERROR] Java not found, please install Java first ``` -------------------------------- ### Start CPU Load Generation - Java Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Creates and starts CPU-intensive background tasks equal to twice the number of available processors. Tasks poll a flag to determine when to terminate. Ensure LoadMaker is imported. ```java import fucking.concurrency.demo.util.LoadMaker; public class ConcurrencyTest { public static void main(String[] args) throws Exception { LoadMaker.makeLoad(); // Run your concurrency demo under sustained CPU load Thread.sleep(5000); LoadMaker.stopLoad(); } } ``` -------------------------------- ### Public API Documentation Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/CONTENTS.txt This section details the public API of the Fucking Java Concurrency project, including the LoadMaker utility class and all demo classes. It provides method signatures, parameter types, return types, and code examples for every public method. ```APIDOC ## API Reference This document provides complete public API documentation for the Fucking Java Concurrency project. ### LoadMaker Utility Class Documentation for the LoadMaker utility class, including its methods and usage. ### Demo Classes Documentation for all 11 demo classes, detailing their purpose, methods, and parameters. ### Inner Classes Documentation for over 15 inner classes, outlining their structure and functionality. ### Method Signatures and Examples - Full method signatures are provided for all public methods. - Parameters, return types, and exception conditions are documented. - Code examples are included for every public method to illustrate usage. ### Field Descriptions Descriptions and type information for over 15 public fields. ``` -------------------------------- ### Demonstrate HashMap Hang with Concurrent Access Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Initializes a HashMap, starts writer threads that insert random keys, and then runs a reader thread that may hang due to HashMap corruption caused by concurrent writes. ```java HashMapHangDemo demo = new HashMapHangDemo(); // Initialize HashMap for (int i = 0; i < 100; i++) { demo.holder.put(i, null); } // Start writer threads Thread thread = new Thread(demo.getConcurrencyCheckTask()); thread.start(); thread = new Thread(demo.getConcurrencyCheckTask()); thread.start(); // Reader thread - may hang due to HashMap corruption for (int i = 0; i < 10000; ++i) { demo.holder.get(i); } ``` -------------------------------- ### Starting Threads for Non-Atomic Increments Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Launches two threads to execute the `ConcurrencyCheckTask`. This usage pattern is common for testing concurrent modifications. ```Java Thread thread1 = new Thread(demo.getConcurrencyCheckTask()); Thread thread2 = new Thread(demo.getConcurrencyCheckTask()); thread1.start(); thread2.start(); ``` -------------------------------- ### Cyclic Thread Pool Deadlock Example Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Illustrates deadlock by creating two thread pools with circular task submission dependencies. Avoid running this code as it will cause a deadlock. ```java ThreadPoolExecutor pool1 = new ThreadPoolExecutor(16, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); ThreadPoolExecutor pool2 = new ThreadPoolExecutor(16, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); Future future = pool1.submit(() -> { return 1 + getUnchecked(pool2.submit(() -> { return 2 + getUnchecked(pool1.submit(() -> { return 3; })); })); }); // All 16 threads in pool1 block waiting for pool2 tasks // All 16 threads in pool2 block waiting for pool1 tasks // DEADLOCK - getUnchecked(future) never returns ``` -------------------------------- ### Lost Update Scenario Explanation Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md Provides a step-by-step example of how concurrent threads can both read the same value of a volatile counter and then independently write back their incremented result, leading to one increment being lost. ```Text Time 1: Thread A reads counter = 5 Time 2: Thread B reads counter = 5 Time 3: Thread A writes counter = 6 Time 4: Thread B writes counter = 6 Result: counter = 6, but two increments occurred! ``` -------------------------------- ### Chain CompletableFuture Async Computations Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Use CompletableFuture to chain asynchronous computations. supplyAsync starts an async task, and thenComposeAsync chains subsequent tasks. ```java CompletableFuture cf1 = supplyAsync(() -> 1, pool1); cf1.thenComposeAsync(x -> cf2.thenApply(...), pool1); ``` -------------------------------- ### Filter Demo Output for Specific Strings Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Use 'grep' to filter the output of a demo, for example, to show only lines containing 'Fuck'. Redirect standard error to standard output using '2>&1' before piping to grep. ```bash ./mvnw compile exec:java -Dexec.mainClass=... 2>&1 | grep "Fuck" ``` -------------------------------- ### General Maven Execution Command (Windows) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Use this command to compile and run any demonstration class using Maven Wrapper on Windows. Replace with the fully qualified name of the class to execute. ```cmd mvnw.cmd clean compile exec:java -Dexec.mainClass= ``` -------------------------------- ### Submit Task to Thread Pool and Get Future Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Submit a task to an ExecutorService and obtain a Future to retrieve the result. The get() method blocks until the result is available. ```java Future future = pool1.submit(() -> { ... }); future.get(); ``` -------------------------------- ### General Maven Execution Command (Linux/macOS) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Use this command to compile and run any demonstration class using Maven Wrapper on Unix-like systems. Replace with the fully qualified name of the class to execute. ```bash ./mvnw clean compile exec:java -Dexec.mainClass= ``` -------------------------------- ### Project Directory Structure Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Illustrates the file and directory layout of the fucking-java-concurrency project. ```text fucking-java-concurrency/ ├── pom.xml ├── README.md ├── docs/ │ ├── zh-CN/ │ │ ├── README.md │ │ └── ConcurrencyMaterial.md │ └── dining-philosophers-problem.jpg └── src/ └── main/ └── java/ └── fucking/ └── concurrency/ └── demo/ ├── CyclicThreadPoolDeadLockDemo.java ├── FinalInitialDemo.java ├── HashMapHangDemo.java ├── InconsistentReadDemo.java ├── InvalidCombinationStateDemo.java ├── InvalidLongDemo.java ├── NoPublishDemo.java ├── ReentrantLockLivelockDemo.java ├── SymmetricLockDeadlockDemo.java ├── SynchronizationOnMutableFieldDemo.java ├── WrongCounterDemo.java └── util/ └── LoadMaker.java ``` -------------------------------- ### Run All Demos in Sequence Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This bash script iterates through a predefined list of Java demo classes and executes each one using Maven, with a 10-second timeout. It's useful for running all demos in a project to check their behavior. ```bash #!/bin/bash DEMOS=( "NoPublishDemo" "HashMapHangDemo" "InvalidCombinationStateDemo" "InvalidLongDemo" "WrongCounterDemo" "SynchronizationOnMutableFieldDemo" "SymmetricLockDeadlockDemo" "ReentrantLockLivelockDemo" "FinalInitialDemo" "InconsistentReadDemo" ) for demo in "${DEMOS[@]}"; do echo "=== Running $demo ===" timeout 10 ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.$demo || true echo done ``` -------------------------------- ### Observe Initial HashMapHangDemo Output Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This is the expected output when the HashMapHangDemo runs correctly before encountering issues. ```text Add loop started in task! Add loop started in task! Start get in main! Got key 0 in round 0 Got key 1 in round 0 ... Got key 9999 in round 0 Got key 0 in round 1 Got key 1 in round 1 ... ``` -------------------------------- ### Run HashMapHangDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the HashMapHangDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.HashMapHangDemo ``` -------------------------------- ### Run FinalInitialDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/README.md Executes the FinalInitialDemo class using Maven wrapper to demonstrate potential issues with non-final variables in constructors. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemo ``` -------------------------------- ### Run CyclicThreadPoolDeadLockDemo (Good Case) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the CyclicThreadPoolDeadLockDemo in its good case scenario (proper solution) using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo good ``` -------------------------------- ### Enable LoadMaker for CPU Contention Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Uncomment the LoadMaker.makeLoad() line in your demo's main method to introduce CPU load. This helps make concurrency problems more observable. ```java public static void main(String[] args) throws Exception { LoadMaker.makeLoad(); // Uncomment this line // ... rest of demo } ``` -------------------------------- ### Run SymmetricLockDeadlockDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the SymmetricLockDeadlockDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SymmetricLockDeadlockDemo ``` -------------------------------- ### Run NoPublishDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the NoPublishDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.NoPublishDemo ``` -------------------------------- ### Limit Demo Output with Tail Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md To manage excessive output from demos, pipe the command's output to 'tail -20' to display only the last 20 lines. ```bash ./mvnw compile exec:java -Dexec.mainClass=... | tail -20 ``` -------------------------------- ### Constructor and Reader/Writer Methods Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Illustrates instruction reordering in a constructor where assignments to `a` and `flag` might be reordered. The `reader` method shows how a thread might observe an inconsistent state due to this reordering. ```java public FinalInitialDemo() { a = 1; flag = true; } public void writer() { demo = new FinalInitialDemo(); // Instruction reordering here } public void reader() { if (flag) { // May see true int i = a * a; // But a still has default value 0 if (i == 0) { System.out.println("Reordering detected!"); // This can happen } } } ``` -------------------------------- ### Run ReentrantLockLivelockDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the ReentrantLockLivelockDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.ReentrantLockLivelockDemo ``` -------------------------------- ### Run SynchronizationOnMutableFieldDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the SynchronizationOnMutableFieldDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SynchronizationOnMutableFieldDemo ``` -------------------------------- ### NoPublishDemo - Expected Behavior (Synchronized) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This output shows the ideal behavior of NoPublishDemo when proper synchronization (like using 'volatile') is applied, indicating the task stops cleanly. ```text ConcurrencyCheckTask started! Set stop to true in main! Exit main. ConcurrencyCheckTask stopped! ``` -------------------------------- ### Run HashMapHangDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/README.md Reproduces the infinite loop problem in HashMap when concurrent put operations occur without synchronization. Use this to see the HashMap hang. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.HashMapHangDemo ``` -------------------------------- ### Run CyclicThreadPoolDeadLockDemo (Bad Case) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the CyclicThreadPoolDeadLockDemo in its bad case scenario using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo ``` -------------------------------- ### Compare Deadlock and Solution Cases Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Compares the behavior of the bad (deadlock) and good (solution) cases of CyclicThreadPoolDeadLockDemo. Run the bad case, wait for it to hang, then terminate and run the good case to observe the difference. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo # [wait for hang] # [press Ctrl+C to terminate] # Now run good case: ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo good # [observe it completes successfully] ``` -------------------------------- ### Run NoPublishDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/README.md Demonstrates how updates to a shared variable might not be visible across threads without proper synchronization. Run this to observe the issue. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.NoPublishDemo ``` -------------------------------- ### Initialize HashMap Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Initialize a HashMap for storing key-value pairs. Note that HashMap is not thread-safe and can lead to corruption under concurrent modification. ```java final Map holder = new HashMap<>(); ``` -------------------------------- ### Run CyclicThreadPoolDeadLockDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/README.md Executes the CyclicThreadPoolDeadLockDemo class using Maven wrapper to demonstrate thread pool deadlocks. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo ``` -------------------------------- ### Initialize ReentrantLock Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Initialize ReentrantLock instances for explicit lock management. Use tryLock with a timeout for non-blocking acquisition. ```java private static final Lock lock1 = new ReentrantLock(); private static final Lock lock2 = new ReentrantLock(); ``` -------------------------------- ### Observe Failed HashMapHangDemo Output Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This output shows the typical failure mode where the HashMapHangDemo hangs indefinitely due to internal corruption. ```text Add loop started in task! Add loop started in task! Start get in main! Got key 0 in round 0 Got key 1 in round 0 ... Got key 4532 in round 0 [hangs indefinitely - no more output] ``` -------------------------------- ### Safe Initialization with Synchronization Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/best-practices.md Utilize synchronized blocks to explicitly control initialization order and ensure that all fields are properly initialized before being read by other threads. This provides explicit ordering guarantees but incurs lock overhead. ```java public class SafeInit { private int a; private boolean flag; private static final Object lock = new Object(); public void initialize() { synchronized (lock) { a = 1; flag = true; } // Exit of synchronized ensures ordering } public int read() { synchronized (lock) { return a; // Guaranteed to be initialized } } } ``` -------------------------------- ### CompletableFuture for Deadlock Avoidance Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Demonstrates how to avoid deadlock using CompletableFuture's asynchronous chaining. This approach decouples task completion from thread pool consumption. ```java ThreadPoolExecutor pool1 = new ThreadPoolExecutor(16, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); ThreadPoolExecutor pool2 = new ThreadPoolExecutor(16, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); CompletableFuture cf1 = supplyAsync(() -> 1, pool1); CompletableFuture cf2 = supplyAsync(() -> 2, pool2); CompletableFuture cf3 = supplyAsync(() -> 3, pool1); Future future = cf1.thenComposeAsync(x -> cf2.thenComposeAsync(y -> cf3.thenApply(z -> x + y + z), pool2), pool1); // Asynchronous chaining - threads are not blocked waiting for results // Pool threads are freed after their task completes, avoiding deadlock int result = getUnchecked(future); // Eventually completes successfully ``` -------------------------------- ### Initialize Random Number Generator Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Initialize a Random instance to generate random integers, often used for creating varied inputs in stress testing. ```java private final Random random = new Random(); ``` -------------------------------- ### Troubleshoot 'mvnw: command not found' Error Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This error indicates that the Maven wrapper script is not found. Ensure you are executing the command from the project's root directory where the 'mvnw' script is located. ```text ./mvnw: command not found ``` -------------------------------- ### Run CyclicThreadPoolDeadLockDemo (Bad Case) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Executes the bad case of CyclicThreadPoolDeadLockDemo to demonstrate a deadlock scenario. The program will hang indefinitely after initial output. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo # Or explicitly: ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.CyclicThreadPoolDeadLockDemo -Dexec.args="bad" ``` -------------------------------- ### Java Constructor Reordering Demo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This snippet demonstrates instruction reordering in Java constructors. It may run indefinitely and occasionally output an error message if reordering occurs. ```java public class FinalInitialDemo { private int a; private boolean flag; public FinalInitialDemo() { a = 1; flag = true; } public static void main(String[] args) throws Exception { // LoadMaker.makeLoad(); // Uncomment this to increase probability while (true) { FinalInitialDemo demo = new FinalInitialDemo(); Thread t = new Thread(() -> { if (demo.flag && demo.a == 0) { System.out.println("Fuck! instruction reordering occurred."); } }); t.start(); t.join(); } } } ``` -------------------------------- ### Run InconsistentReadDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the InconsistentReadDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InconsistentReadDemo ``` -------------------------------- ### Randomized Backoff for Livelock Prevention Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/best-practices.md This snippet demonstrates how to implement randomized backoff to recover from livelock. It retries acquiring locks with increasing, randomized delays up to a maximum number of retries. ```java int maxRetries = 100; int retryCount = 0; while (retryCount < maxRetries) { if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) { try { if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) { // Success - have both locks return doWork(); } } finally { lock1.unlock(); } } // Failed - backoff with randomization long backoff = (long)(Math.random() * (1L << Math.min(++retryCount, 10))); Thread.sleep(backoff); } ``` -------------------------------- ### Livelock Demo: Timeout-Based Lock Acquisition Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md This Java code demonstrates a livelock scenario where two threads attempt to acquire two locks in opposite orders with timeouts. If a thread fails to acquire the second lock within the timeout, it releases the first lock and retries, potentially leading to an infinite loop of lock acquisition attempts without progress. ```Java static final Lock lock1 = new ReentrantLock(); static final Lock lock2 = new ReentrantLock(); // Thread 1 while (counter++ < 10_000) { if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) { if (lock2.tryLock()) { // Success! break; } else { lock1.unlock(); continue; // Retry } } } // Thread 2 while (counter++ < 10_000) { if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) { // Opposite order if (lock1.tryLock()) { // Success! break; } else { lock2.unlock(); continue; // Retry } } } ``` -------------------------------- ### Enabling CPU Load with LoadMaker Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This code snippet shows how to uncomment the LoadMaker.makeLoad() line within the main method. This is an optional step to increase the probability of observing instruction reordering by introducing artificial CPU load. ```java public static void main(String[] args) throws Exception { LoadMaker.makeLoad(); // Uncomment this while (true) { // ... demo code } } ``` -------------------------------- ### Use Timeout-Based Locks with Backoff Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/best-practices.md Employ `tryLock` with a timeout and a backoff strategy to avoid indefinite waits. This method prevents deadlocks without requiring a strict lock order but can introduce complexity and latency. ```java Lock lock1 = new ReentrantLock(); Lock lock2 = new ReentrantLock(); boolean tryBothLocks() { boolean lock1Acquired = false; boolean lock2Acquired = false; try { lock1Acquired = lock1.tryLock(50, TimeUnit.MILLISECONDS); if (!lock1Acquired) return false; lock2Acquired = lock2.tryLock(50, TimeUnit.MILLISECONDS); if (!lock2Acquired) return false; return true; // Have both locks } finally { if (!lock2Acquired && lock1Acquired) { lock1.unlock(); } } } // In work loop while (!tryBothLocks()) { Thread.sleep((long)(Math.random() * 100)); // Backoff } ``` -------------------------------- ### Runnable for Lock Acquisition (Lock1 then Lock2) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md This task demonstrates deadlock by acquiring two locks in a specific order (lock1 then lock2) within an infinite loop. It's designed to be run concurrently with `ConcurrencyCheckTask2`. ```Java private static class ConcurrencyCheckTask1 implements Runnable { @Override @SuppressWarnings("InfiniteLoopStatement") public void run() { System.out.println("ConcurrencyCheckTask1 started!"); while (true) { synchronized (lock1) { synchronized (lock2) { System.out.println("Hello1"); } } } } } ``` -------------------------------- ### Run WrongCounterDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the WrongCounterDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.WrongCounterDemo ``` -------------------------------- ### Java Demo of Invalid Combined State Reads Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md Demonstrates how reading volatile fields between updates can lead to observing invalid combinations. This scenario highlights the need for atomic operations when dealing with related fields. ```java volatile int state1; volatile int state2; // Must always equal state1 * 2 // Writer thread int rand = random.nextInt(1000); state1 = rand; // Write state1 state2 = rand * 2; // Write state2 (state2 not yet updated) // Reader thread - can see: // state1 = new_value, state2 = old_value (invalid combination!) int i1 = state1; int i2 = state2; if (i1 * 2 != i2) { System.err.println("Invalid combination detected!"); } ``` -------------------------------- ### Fix Deadlock Using Ordered Lock Sets Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Illustrates an alternative fix for deadlock by using a sorted set to manage lock acquisition order. ```java static final SortedSet locks = new TreeSet<>( Arrays.asList(lock1.hashCode(), lock2.hashCode()) ); ``` -------------------------------- ### Verify HashMap Hang with jstack Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Use jps to find the process ID and then jstack to inspect the thread dump, confirming the main thread is stuck in HashMap code. ```bash jps # Get process ID jstack | grep -A 20 "main" ``` -------------------------------- ### FinalInitialDemo Class Definition Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md The full definition of the FinalInitialDemo class, illustrating field initialization and methods for writing and reading potentially reordered values. ```java public class FinalInitialDemo { private int a; private boolean flag; private FinalInitialDemo demo; public FinalInitialDemo() { a = 1; flag = true; } public void writer() { demo = new FinalInitialDemo(); } public void reader() { if (flag) { int i = a * a; if (i == 0) { System.out.println("Fuck! instruction reordering occurred."); } } } } ``` -------------------------------- ### Non-Atomic Long Read/Write Demo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md Demonstrates how reading and writing a non-volatile long can result in observing torn values, where the high and low 32-bits come from different writes. This occurs because long operations are not guaranteed to be atomic. ```Java long count = 0; // Non-volatile // Writer thread for (int i = 0; ; i++) { final long l = i; count = l << 32 | l; // Both halves are identical } // Reader thread long l = count; long high = l >>> 32; // Extract upper 32 bits long low = l & 0xFFFFFFFFL; // Extract lower 32 bits if (high != low) { System.err.println("Torn long detected!"); } ``` -------------------------------- ### NoPublishDemo - Observed Behavior (Without volatile) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md This output demonstrates the problem in NoPublishDemo without 'volatile'. The task thread hangs indefinitely because it doesn't see the 'stop' flag update from the main thread. ```text ConcurrencyCheckTask started! Set stop to true in main! Exit main. [hangs indefinitely - task never stops] ``` -------------------------------- ### stopLoad() Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Signals all load-generating threads to terminate. Sets the global `isLoadMade` flag to `false`, which causes all background threads spawned by `makeLoad()` to exit their infinite loops and terminate gracefully. ```APIDOC ## stopLoad() ### Description Signals all load-generating threads to terminate. Sets the global `isLoadMade` flag to `false`, which causes all background threads spawned by `makeLoad()` to exit their infinite loops and terminate gracefully. Called after concurrent demonstrations complete to clean up resources. ### Method ```java public static void stopLoad() ``` ### Parameters None ### Return Type `void` ### Example ```java LoadMaker.makeLoad(); // ... run demo ... LoadMaker.stopLoad(); ``` ``` -------------------------------- ### Verify Deadlock with jstack Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Commands to identify the Java process ID and then inspect its threads to confirm a deadlock state. ```bash jps ``` ```bash jstack ``` -------------------------------- ### Java Runnable for Visibility Demo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md Implements Runnable to demonstrate a visibility issue by continuously checking a non-volatile field. Use when a thread needs to react to changes in a shared field without guaranteed visibility. ```java private class ConcurrencyCheckTask implements Runnable { @Override @SuppressWarnings({"WhileLoopSpinsOnField", "StatementWithEmptyBody"}) public void run() { System.out.println("ConcurrencyCheckTask started!"); while (!stop) { } System.out.println("ConcurrencyCheckTask stopped!"); } } ``` ```java Thread thread = new Thread(demo.getConcurrencyCheckTask()); thread.start(); ``` -------------------------------- ### Java Constructor Reordering Demo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md Illustrates instruction reordering in a Java constructor. Non-final fields 'a' and 'flag' are assigned values, but due to potential reordering, another thread observing 'flag' as true might find 'a' still uninitialized (default value 0). This can lead to unexpected behavior like 'a * a' evaluating to 0. ```java private int a; private boolean flag; public FinalInitialDemo() { a = 1; flag = true; // May be reordered to: // flag = true; // a = 1; // Or even further reordered } // Thread 1 demo = new FinalInitialDemo(); // Thread 2 if (flag) { // Sees true int i = a * a; // But a is still 0 (default)! if (i == 0) { System.out.println("Reordering!"); // This can happen } } ``` -------------------------------- ### Stub Listener Class Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md A placeholder class used to test collection size in concurrency scenarios. It has no functional implementation. ```Java static class Listener { // stub class } ``` -------------------------------- ### Use volatile for Simple Visibility Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/best-practices.md Use the `volatile` keyword for simple boolean flags or atomic reference updates to ensure visibility across threads. It offers minimal performance overhead but does not guarantee atomicity for compound operations. ```java private volatile boolean stop = false; // Writer thread stop = true; // Reader thread while (!stop) { // Works correctly - visibility guaranteed } ``` -------------------------------- ### Run InvalidLongDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the InvalidLongDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidLongDemo ``` -------------------------------- ### Runnable for Adding Listeners Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md This task repeatedly calls `addListener` with new `Listener` objects. It's used to show issues with concurrent collection modifications. ```Java private class ConcurrencyCheckTask implements Runnable { @Override public void run() { System.out.println("ConcurrencyCheckTask started!"); for (int i = 0; i < ADD_COUNT; ++i) { addListener(new Listener()); } System.out.println("ConcurrencyCheckTask stopped!"); } } ``` -------------------------------- ### Runnable for Lock Acquisition (Lock2 then Lock1) Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/types-and-classes.md This task demonstrates deadlock by acquiring two locks in the reverse order (lock2 then lock1) within an infinite loop. It's designed to cause deadlock when run concurrently with `ConcurrencyCheckTask1`. ```Java private static class ConcurrencyCheckTask2 implements Runnable { @Override @SuppressWarnings("InfiniteLoopStatement") public void run() { System.out.println("ConcurrencyCheckTask2 started!"); while (true) { synchronized (lock2) { synchronized (lock1) { System.out.println("Hello2"); } } } } } ``` -------------------------------- ### Fix Deadlock by Enforcing Consistent Lock Ordering Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/execution-guide.md Demonstrates the corrected code for two tasks to prevent deadlock by acquiring locks in the same order. ```java // Task1 while (true) { synchronized (lock1) { synchronized (lock2) { System.out.println("Hello1"); } } } ``` ```java // Task2 - SAME ORDER while (true) { synchronized (lock1) { synchronized (lock2) { System.out.println("Hello2"); } } } ``` -------------------------------- ### Run InvalidCombinationStateDemo Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/project-structure.md Execute the InvalidCombinationStateDemo using Maven. This command compiles the project and runs the specified main class. ```bash ./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidCombinationStateDemo ``` -------------------------------- ### Stop CPU Load Generation - Java Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/api-reference.md Signals all load-generating threads to terminate by setting a global flag to false. This allows background threads to exit their loops gracefully. Call this after your demo completes. ```java LoadMaker.makeLoad(); // ... run demo ... LoadMaker.stopLoad(); ``` -------------------------------- ### Demo: Add Listener with Mutable Field Reference Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/concurrency-issues.md This code snippet illustrates a race condition where synchronizing on a mutable list reference and then reassigning that reference leads to lost updates. Use this pattern with caution as it is prone to concurrency issues. ```java private volatile List listeners = new CopyOnWriteArrayList<>(); public void addListener(Listener listener) { synchronized (listeners) { List results = new ArrayList<>(listeners); results.add(listener); listeners = results; // Field reassignment! } } ``` ```java // Thread 1 // Thread 2 synchronized (listeners) { synchronized (listeners) { // listeners = [A, B] // listeners = [A, B] List r = new ArrayList(L); r.add(C); listeners = r; // [A, B, C] // [A, B, D] -- lost C! } } ``` -------------------------------- ### Leverage Higher-Level Concurrency Utilities Source: https://github.com/oldratlee/fucking-java-concurrency/blob/master/_autodocs/best-practices.md Utilize modern Java concurrency utilities like `ConcurrentHashMap`, `ExecutorService`, and `BlockingQueue` to avoid explicit lock management. These utilities offer expert implementations and are generally easier to reason about. ```java // ConcurrentHashMap - no deadlock possible Map map = new ConcurrentHashMap<>(); map.put("key", 1); Integer value = map.get("key"); // Executors - manage thread lifecycles ExecutorService executor = Executors.newFixedThreadPool(10); executor.submit(() -> { /* work */ }); // Queues - producer-consumer pattern BlockingQueue queue = new LinkedBlockingQueue<>(); queue.put(task); // Producer Task t = queue.take(); // Consumer ```