This project benchmarks different synchronization techniques for incrementing a counter in Java. It demonstrates the performance and correctness trade-offs between various concurrency mechanisms, including locks, atomic operations, and volatile variables.
The Main.java
program runs several tests, each incrementing a counter 50 million times (per thread), using different synchronization strategies:
- Single thread: No synchronization, one thread increments a local variable.
- Single thread with lock: One thread increments a local variable, but each increment is protected by a
ReentrantLock
. - Two threads with lock: Two threads increment a shared variable, each increment protected by a
ReentrantLock
. - Single thread with CAS: One thread increments an
AtomicLong
using compare-and-swap (CAS). - Two threads with CAS: Two threads increment a shared
AtomicLong
using CAS. - Single thread with volatile: One thread increments a
volatile
field. - Two threads with volatile: Two threads increment a shared
volatile
field (not atomic, for demonstration).
Each test measures and prints the time taken (in milliseconds) to complete the increments.
- The main method prints a table of results for each synchronization method.
- Each test is implemented as a static method in
Main.java
. - For multi-threaded tests, two threads are started and joined.
- The volatile test with two threads demonstrates that
volatile
does not guarantee atomicity, and is included for educational purposes.
- Build the project (if using Maven):
mvn compile
- Run the program:
Or, if you prefer to run directly:
mvn exec:java -Dexec.mainClass="org.example.Main"
javac -d target/classes src/main/java/org/example/Main.java java -cp target/classes org.example.Main
Method | Time (ms)
-----------------------------------------------
Single thread | 100
Single thread with lock | 500
Two threads with lock | 1200
Single thread with CAS | 200
Two threads with CAS | 400
Single thread with volatile | 120
Two threads with volatile | 300
(Times are illustrative; actual results depend on your hardware.)
- The two-thread volatile test is not thread-safe and may produce incorrect results. It is included to show the dangers of using
volatile
for compound actions. - Use this benchmark to understand the performance and correctness implications of different synchronization techniques in Java.
This project is for educational purposes.