Implementing Thread-Safe Counters in Java

In concurrent programmnig, a shared counter must be thread-safe to prevent data races and inconsistencies when accessed by multiple threads simultaneously. Two primary approaches to achieve this are using atomic variables and explicit synchronization via locks.

Using AtomicInteger

AtomicInteger provides atomic operations without requiring explicit locking, utilizing low-level CPU instructions for thread safety.

public class AtomicBasedCounter implements Runnable {
    private static final AtomicInteger sharedCounter = new AtomicInteger(0);

    public static void performIncrement() {
        if (sharedCounter.get() < 1000) {
            int updatedValue = sharedCounter.incrementAndGet();
            System.out.println("Thread " + Thread.currentThread().getName() + " processed count: " + updatedValue);
        }
    }

    @Override
    public void run() {
        while (true) {
            performIncrement();
            try {
                Thread.sleep(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 6; i++) {
            AtomicBasedCounter task = new AtomicBasedCounter();
            new Thread(task).start();
        }
    }
}

Using Synchronized Methods

The synchronized keyword ensures that only one thread can execute the method at a time, porviding mutual exclusion.

public class SynchronizedCounter {
    private int value = 0;

    public synchronized void increase() {
        value++;
        System.out.println("Thread " + Thread.currentThread().getName() + " updated value to: " + value);
    }

    public static void main(String[] args) {
        SynchronizedCounter counterInstance = new SynchronizedCounter();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                for (int j = 0; j < 100; j++) {
                    counterInstance.increase();
                    try {
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

Tags: java Concurrency Thread Safety AtomicInteger Synchronization

Posted on Thu, 07 May 2026 13:32:40 +0000 by andrewgauger