Skip to content

Commit a12e011

Browse files
committed
feat: implement thread-safe counter using AtomicInteger vs volatile
WHAT was added: - A class `VolatileCounter2` demonstrating difference between `volatile` and `AtomicInteger`. - Two worker threads increment a shared counter 1000 times each. - Shows how `AtomicInteger.incrementAndGet()` ensures atomicity and prevents lost updates. - Prints final counter value after both threads complete. WHY this matters: - `volatile` only guarantees visibility (all threads see latest value), but it does not make compound operations (like `counter++`) atomic. - With plain `volatile`, increments can be lost under race conditions. - `AtomicInteger` provides atomic methods (`incrementAndGet`, `getAndAdd`, etc.) using low-level Compare-And-Swap (CAS), ensuring correctness without locks. - This example highlights when to use `volatile` vs when to prefer `AtomicInteger`. HOW it works: 1. Shared `AtomicInteger counter` initialized to 0. 2. Two threads concurrently call `vc2.increment()` 1000 times each. 3. `incrementAndGet()` ensures thread-safe increments. 4. After both threads join, final result is `2000` (no lost updates). 5. Contrast: with plain `volatile int counter`, result could be less than 2000 due to race conditions. Key Concepts: - Visibility vs atomicity: `volatile` ensures visibility, `AtomicInteger` ensures both visibility + atomicity. - CAS operation: retries until update succeeds (non-blocking). - Lightweight alternative to `synchronized` or `ReentrantLock`. REAL-LIFE APPLICATIONS: - Web servers → counting number of requests served in real time safely across multiple threads. - Rate limiting → tracking API calls per user without race conditions. - Monitoring systems → counting events/logs without locking overhead. - Thread-safe statistics → updating counters in analytics pipelines. - Producer-consumer systems → maintaining counters for produced vs consumed messages. LIMITATIONS: - `AtomicInteger` works for simple numeric counters. - For more complex atomic updates (multiple variables), use locks or `AtomicReference`. - Busy CAS retry loops may cause performance overhead under very high contention. KEYWORDS: volatile atomic integer concurrency race-condition CAS compare-and-swap thread-safe counter. Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent c8923e2 commit a12e011

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import java.util.concurrent.atomic.AtomicInteger;
2+
3+
public class VolatileCounter2 {
4+
//private int counter = 0;
5+
//private volatile int counter = 0;
6+
7+
private AtomicInteger counter = new AtomicInteger(0);
8+
//Thread safe. ek baar mai bas ek thread kaam karega. u also use synchronization and lock.
9+
10+
public void increament() {
11+
//counter++;
12+
13+
int i = counter.incrementAndGet();
14+
}
15+
16+
public int getCounter() {
17+
//return counter;
18+
19+
return counter.get();
20+
}
21+
22+
public static void main(String[] args) throws InterruptedException {
23+
VolatileCounter2 vc2 = new VolatileCounter2();
24+
25+
Thread t3 = new Thread(() -> {
26+
for(int i=0; i<1000; i++) {
27+
vc2.increament();
28+
}
29+
});
30+
31+
Thread t4 = new Thread(() -> {
32+
for(int i=0; i<1000; i++) {
33+
vc2.increament();
34+
}
35+
});
36+
37+
t3.start();
38+
t4.start();
39+
40+
t3.join();
41+
t4.join();
42+
43+
System.out.println(vc2.getCounter());
44+
}
45+
}
46+
47+
/*
48+
===========================
49+
volatile vs AtomicInteger
50+
===========================
51+
52+
1. volatile int counter = 0;
53+
- Threads ko latest value dikhegi.
54+
- Lekin counter++ is NOT atomic (read + add + write).
55+
- Example: Thread A and B dono read karte hain same old value,
56+
dono increment karte hain -> ek update lost ho jaata hai.
57+
58+
2. AtomicInteger counter = new AtomicInteger(0);
59+
- Methods like incrementAndGet(), getAndAdd() are atomic.
60+
- Internal implementation uses CAS (Compare-And-Swap).
61+
- No lost updates, thread-safe without explicit locks.
62+
63+
3. Alternative:
64+
- synchronized methods ya ReentrantLock use kar sakte ho,
65+
lekin AtomicInteger zyada lightweight aur efficient hota hai
66+
simple counters ke liye.
67+
*/

0 commit comments

Comments
 (0)