Four ways to implement a synchronized counter in Java

Dilan Tharaka
3 min readAug 27, 2019

--

Photo by Djim Loic on Unsplash

A synchronized counter is a counter which can be updated using several threads. You may need to implement a synchronized counter in day to day programming tasks, and this is a common interview question in multithreaded programming. In terms of multithreaded programming Java provides many ways to implement synchronization. Let’s see how we can implement a synchronized counter in Java (For simplicity, we’re implementing a counter which only increments the value, but there’re situations to implement counters with both increment and decrement features).

Solution 0 ( The wrong way)

Let’s assume; I don’t know any synchronization methods in Java, then this is how I would implement a multithreaded counter.

This has a thread pool where each thread is trying to access the counter and increase it. There’s no control over the access to counter variable.

What would go wrong with this implementation?

The following is a part of the output generated by the above program.

pool-1-thread-1 : 20
pool-1-thread-1 : 21
pool-1-thread-2 : 21
pool-1-thread-2 : 22

In here thread 1 and thread 2 both are printing the same value. What happens here is both threads are accessing the counter variable at the same time, and both are updating its value. This is what we call a race condition in multithreading. To avoid this, we should synchronize access to the counter variable. Let’s see how to do that.

Solution 1( Using a synchronized block )

The most popular way of implementing synchronization in Java is using synchronized blocks, synchronized methods or using synchronized variables. In this code example, I’ve used synchronized block, but using the other two methods is also feasible.

In this code synchronized block is applying on the object lock. Since that object is shared between all the threads, only one thread can be inside of the synchronized block at one time.

Solution 2( Using an atomic variable )

Atomic variables are just like other variables in Java, but they have atomic operations such as incrementAndGet and compareAndSet . These operations are guaranteed to execute atomically, which means these operations would not get interfered in multithreaded environments. In Java, there’re several types of atomic variables such as AtomicInteger , AtomicBoolean and AtomicIntegerArray.

Solution 3( Using a concurrent lock )

java.util.concurrent.lock the package comes up with several implementations of Lock interface. These Locks are easier to use and more flexible than the synchronized blocks. Following code uses ReentrantLock. But depending on your needs, you may use another lock in your code.

Solution 4( Using a Semaphore )

Semaphores are one of the famous methods of achieving synchronization in programming. They control access to a shared resource using a counter. In the code below, you won’t see much difference in semaphores with locks. But keep in mind that a semaphore can be initiated with an initial count of more than 1 and can be used in scenarios where a thread should wait until the counter becomes zero.

In this article, I’ve discussed 4 different ways of implementing a synchronized counter in Java.

  • Synchronized Block
  • Atomic Variable
  • Concurrent Lock
  • Semaphore

These methods are not just for implementing synchronized counters but useful for all day to day multithreaded programming tasks.

If you want to learn more about Java multithreaded programming in Java, I recommend reading the following books

Happy Coding 💻

--

--

Dilan Tharaka
Dilan Tharaka

Written by Dilan Tharaka

Software engineer curious about how things actually work

No responses yet