🛡️ What is a Race Condition in Java, and how it can be prevented using synchronized and AtomicInteger
Tags: java, programming, tutorial, webdev
Published: 2023-06-17 15:25:21

## Table of Contents
&nbsp;1. [Problem 1 — Main thread doesn't wait for other threads to finish](#problem-1)
&nbsp;2. [Solution — `future.get()`](#solution)
&nbsp;3. [Problem 2 — Multiple threads have access to the same variable at a time](#problem-2-multiple-threads-have-access-to-the-same-variable-at-a-time)
&nbsp;4. [Solution — `AtomicInteger`](#solution-raw-atomicinteger-endraw-)
&nbsp;5. [Problem 3 — `AtomicInteger` may be not enough](#problem-3-raw-atomicinteger-endraw-may-be-not-enough)
&nbsp;6. [Solution — `synchronized` keyword](#solution-raw-synchronized-endraw-keyword)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Synched non-static method](#synched-nonstatic-method)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Another synched non-static method](#another-synched-nonstatic-method)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Simple unsynched method](#simple-unsynched-method)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Static synched method](#static-synched-method)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Sounds overwhelming. How to understand it?](#sounds-overwhelming-how-to-understand-it)

&nbsp;7. [AtomicInteger vs synchronized](#-raw-atomicinteger-endraw-vs-raw-synchronized-endraw-)
&nbsp;8. [Conclusion](#conclusion)
&nbsp;9. [Useful resources](#useful-resources)


Hello, everyone! First of all, thank you all for the amazing feedback and support you gave me on my [previous post](https://dev.to/danielrendox/thread-runnable-callable-executorservice-and-future-all-the-ways-to-create-threads-in-java-2o86). Thanks @thepracticaldev for supporting aspiring writers. I'm so happy to be back with another article about how to synchronize threads!

Well, why should we synchronize them if the essence of multithreading is to perform operations asynchronously? Because with the benefits of multithreading come challenges. In this article, we’ll learn about problems that occur and ways to solve them.

Let’s consider this code:

```java
public class DonutStorage {
    private int donutsNumber;
    public DonutStorage(int donutsNumber) {this.donutsNumber = donutsNumber;}
    public int getDonutsNumber() {return donutsNumber;}
    public void setDonutsNumber(int donutsNumber) {this.donutsNumber = donutsNumber;}
}

public class Consumer {
    private final DonutStorage donutStorage;
    public Consumer(DonutStorage donutStorage) {this.donutStorage = donutStorage;}

    /**
     * Subtracts the given number from the DonutStorage's donutsNumber.
     * @param numberOfItemsToConsume Number that will be subtracted from the donutsNumber
     */
    public void consume(int numberOfItemsToConsume) {
        donutStorage.setDonutsNumber(donutStorage.getDonutsNumber() - numberOfItemsToConsume);
    }
}

public class Main {
    public static void main(String[] args) {
        int consumersNumber = 10;
        DonutStorage donutStorage = new DonutStorage(20);
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        for (int i = 0; i < consumersNumber; i++) {
            executor.submit(() -> new Consumer(donutStorage).consume(1));
        }
        executor.shutdown();

        System.out.println("Number of remaining donuts: " + donutStorage.getDonutsNumber());
    }
}
```

Here we have a simple program for a donut shop that counts the number of donuts. This shop probably has a server, which gets data from clients. As there are many clients who consume donuts, and the server must serve them simultaneously, it will have different threads each dedicated to one user.

To realize this in code, we create an `ExecutorService` with the number of threads equal to the available number of cores. Then we want it to serve the `consumerNumber` of clients, so there is a for loop that submits tasks to create a new `Consumer` that will consume items from the `DonutStorage`, and print the number of remaining donuts on the console.

Let’s assume that there are 10 consumers, each buys 1 donut, and we have 20 donuts in total. To prevent errors, if a user wants more donuts than there are in stock, the remaining donuts will be sold (the donutsNumber will be set to 0).

## Problem 1

So we expect the number of remaining donuts to be 10, but I have the following printed (you may have a different result):

```
Number of remaining donuts: 19
```

### Question

Why is that so? This problem is not connected with race condition. So go ahead and make a guess! C’mon, you should know the answer from the [previous article](https://dev.to/danielrendox/thread-runnable-callable-executorservice-and-future-all-the-ways-to-create-threads-in-java-2o86)!

### Answer

Because we didn’t call `join` so the main thread doesn’t wait for the others to finish.

Don’t get confused by `executor.shutdown()`. It doesn’t mean that the code below it is executed after the executor is shut down. Look, the main thread does 5 things:

- creates some variables;
- creates an executor;
- submits tasks to the executor;
- shuts down the executor;
- prints the result;

These operations are done sequentially, but, when it tells the executor to shut down, it doesn’t actually wait until it happens. According to the documentation of `shutdown()`, when this method is called, `ExecutorService`

> Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
> 

However, the main thread isn’t blocked and continues its work.

In other words, in my situation, only 1 of the 10 users had managed to get a donut, when the main thread printed the number of remaining ones. As threads can be scheduled in other ways, rerunning the program, we may get a different result.

## Solution

But how can we join the threads? With a simple `Thread` we would write `myThread.join()`. But how to do it with `ExecutorService`?

It’s not appropriate to use  `ExecutorService` in this way. We should harness its `Future` power instead.
Even though, `executor.submit(()->{})` submits a `Runnable`, the method still returns a `Future` that never contains any value inside but can tell when the task gets finished.

To get the desired functionality, we should keep these futures from each submission in a list and then loop through them to make sure all the tasks are finished:

```java
public class Main {
    public static void main(String[] args) {
        int consumersNumber = 10;
        DonutStorage donutStorage = new DonutStorage(20);
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        List<Future<?>> futures = new ArrayList<>(consumersNumber);
        for (int i = 0; i < consumersNumber; i++) {
            futures.add(executor.submit(() -> new Consumer(donutStorage).consume(1)));
        }
        executor.shutdown();

        // make the main thread wait for others to finish
        for (Future<?> future: futures) {
            try {
                future.get();
            } catch (InterruptedException | ExecutionException e) {
                System.out.println("Exception while getting from future" + e.getMessage());
                e.printStackTrace();
            }
        }

        System.out.println("Number of remaining donuts: " + donutStorage.getDonutsNumber());
    }
}
```

This way the main thread gets blocked (waits) until the other threads finish their work.

BTW, it’s wrong to assume that getting only the final future is enough because the tasks aren’t done sequentially.

You can compare the old and the updated versions [here](https://github.com/DanielRendox/ThreadSynchronizationInJava/commit/2f5d8b5783b94fab89383fa53a86a23a0b22a75d).

## Problem 2 — Multiple threads have access to the same variable at a time

Change the main method and run the code. Output:

```
Number of remaining donuts: 10
```

The problem is solved, right? Unfortunately, no. Try and run it again! Output:

```
Number of remaining donuts: 12
```

### Explanation

Let's examine what may have happened.

You see, multiple threads have access to the `private int donutsNumber` in the `DonutStorage` at the same time. To change the value of this variable they should:

1. Get the variable
2. Set the variable

Because of the thread interleaving we may get something like this:

<table>
  <tr>
    <td>The 5th thread reads the value of 15</td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td>The 6th thread reads the value of 15 (as the 5th user hasn’t yet changed the value)</td>
  </tr>
  <tr>
    <td>The 5th thread changes the value to 14</td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td>The 6th thread changes the value to 14</td>
  </tr>
</table>


Blank in this table means that the thread for whatever reason sits idle, which is completely normal.

So everything goes OK until the 5th and the 6th threads read the same value simultaneously and one item is automatically not counted. And it may not be the only case. **This behavior is called a race condition.**


![Multithreaded programming: threory — each doggy eats from its bowl, actual — the doggies messed up with the bowls, each eats not from its bowl, the food is on the floor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ss99qvwvlwbd3kdhodzu.jpg)

## Solution — `AtomicInteger`

To solve a synchronization problem we first should check if the solution is already written for us. In this case, there is one - `AtomicInteger`. 

An atomic operation is an operation that is done at once. As we’ve seen, subtracting a number from a variable is not an atomic operation. Similarly, when you write `i++`, it seems to be atomic, but it’s not because the value is read and then written (so two operations not one).

There are classes like `AtomicInteger`, `AtomicLong`, `AtomicBoolean`, etc. They internally make these operations atomic and in this way solve the problem.

Here is the improved code:

```java
public class DonutStorage {
    private final AtomicInteger donutsNumber;
    public DonutStorage(int donutsNumber) {
        this.donutsNumber = new AtomicInteger(donutsNumber);
    }
    public AtomicInteger getDonutsNumber() {return donutsNumber;}
}

public class Consumer {
    private final DonutStorage donutStorage;
    public Consumer(DonutStorage donutStorage) {
        this.donutStorage = donutStorage;
    }
    /**
     * Subtracts the given number from the DonutStorage's donutsNumber.
     * @param numberOfItemsToConsume Number that will be subtracted from the donutsNumber
     */
    public void consume(int numberOfItemsToConsume) {
        donutStorage.getDonutsNumber().addAndGet(-numberOfItemsToConsume);
    }
}
```

Firstly, we change the `donutsNumber`’s type to `AtomicInteger`, modify the respective getter, and delete the setter because we no longer need it. Then, the `Consumer`’s `consume` method should be modified to work with `AtomicInteger`. Let’s use its `addAndGet`method, which *atomically* adds the given number to the current value or subtracts from it if the given param is negative.

Mind you, it wouldn’t work if we’d modified getters and setters for `donutsNumber` to return `int` instead of making the `consume` method work with `AtomicInteger`. That’s because different threads would’ve ended up using `int` and bypassing the atomic nature of `AtomicInteger`. So be careful with this and make sure that you are using it correctly. However, this problem will be explained in more detail in the following section.

You can compare the old and the updated versions [here](https://github.com/DanielRendox/ThreadSynchronizationInJava/commit/de753f8c285dd5b2e74add4f11b067a9a68aab33?diff=split).

## Problem 3 — `AtomicInteger` may be not enough

Now consumers are allowed to take as many items as they want, but the number of donuts is limited. Let’s improve the program to satisfy this requirement.

So we’ll add an if-statement to the `consume` method that checks if the given number is bigger than the number of donuts in stock. When so, the number of donuts in stock will be set to 0. But it’ll be also good to know how many donuts a consumer actually consumes so let’s make the `consume` method return this number. We’ll also change the lambda in the `Main` to print the results in the form of “`Thread’s name` consumed `number of items`”. To test how it works, let’s also make the consumers try to consume more than is available, say 3 items each. The changes may look like this:

```java
futures.add(executor.submit(() -> {
    Consumer consumer = new Consumer(donutStorage);
    System.out.println(Thread.currentThread().getName() + " consumed " +
            consumer.consume(3)); // changed the number from 1 to 3
}));

/**
 * Subtracts the given number from the DonutStorage's donutsNumber. If the given number is bigger
 * than the number of donuts in stock, sets the donutsNumber to 0.
 * @param numberOfItemsToConsume Number that will be subtracted from the donutsNumber
 * @return the number of consumed items
 */
public int consume(int numberOfItemsToConsume) {
    AtomicInteger donutsNumber = donutStorage.getDonutsNumber();
    // if there aren't enough donuts in stock, consume as many as there are
    if (numberOfItemsToConsume > donutsNumber.get()) {
        int result = donutsNumber.get();
        donutsNumber.set(0);
        return result;
    }

    donutStorage.getDonutsNumber().addAndGet(-numberOfItemsToConsume);
    return numberOfItemsToConsume;
}
```

You can compare the old and the updated versions [here](https://github.com/DanielRendox/ThreadSynchronizationInJava/commit/e00c502bc0471dfaf43ab358d04e43ac91ad3917?diff=unified).

Running the code, we can get the desired result!

```
pool-1-thread-1 consumed 3
pool-1-thread-3 consumed 3
pool-1-thread-6 consumed 3
pool-1-thread-8 consumed 0
pool-1-thread-7 consumed 2
pool-1-thread-1 consumed 0
pool-1-thread-2 consumed 3
pool-1-thread-5 consumed 3
pool-1-thread-4 consumed 3
pool-1-thread-7 consumed 0
Number of remaining donuts: 0
```

You see how threads interleave. The one which gets only 2 items doesn’t go after the others that get 3 items. It’s completely OK. What’s not OK is that if we add a simple action that takes some time into the `consume` method, for example, printing some random text it will break the program. Check this out:

```java
public int consume(int numberOfItemsToConsume) {
    AtomicInteger donutsNumber = donutStorage.getDonutsNumber();
    // if there aren't enough donuts in stock, consume as many as there are
    if (numberOfItemsToConsume > donutsNumber.get()) {
        int result = donutsNumber.get();
        donutsNumber.set(0);
        return result;
    }
    
    // printing some random text breaks the program
    System.out.println("The UFO flew in and left this inscription here.");
    
    donutStorage.getDonutsNumber().addAndGet(-numberOfItemsToConsume);
    return numberOfItemsToConsume;
}
```

Output:

```
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
The UFO flew in and left this inscription here.
pool-1-thread-4 consumed 3
pool-1-thread-4 consumed -4
pool-1-thread-4 consumed 0
pool-1-thread-6 consumed 3
pool-1-thread-5 consumed 3
pool-1-thread-7 consumed 3
pool-1-thread-3 consumed 3
pool-1-thread-2 consumed 3
pool-1-thread-1 consumed 3
pool-1-thread-8 consumed 3
Number of remaining donuts: 0
```

Despite the resulting number still being 0, we have issues with the resulting value of `consume` method. Why is that so?

That’s because printing some text introduces a delay resulting in the interleaving of the threads in a way that causes another **race condition**. Add it doesn’t mean that we shouldn’t just write some random text and the program will work fine. On another person’s computer, it may return an unexpected output without the random text, because their computer may be slower/faster/less or more busy, etc.

The question is why the program breaks despite `AtomicInteger`. Another question is why the race condition doesn’t happen in the previous section’s code. And you are about to get the answers.

### Explanation

That’s because `AtomicInteger` only provides atomic access to the value it holds and uses a non-blocking algorithm. And that means that multiple threads may access the value at the same time. Whereas, our program contains `consume` method that gets executed by multiple threads simultaneously.

Here is a possible scenario:

<table>
  <tr>
    <td>The 6th thread reads the value of 5 and gets false in the if-condition</td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td>The 7th thread reads the value of 5 and gets false in the if-condition either</td>
  </tr>
  <tr>
    <td>The 6th thread atomically reads 5 and writes 2</td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td>The 7th thread atomically reads 2 and writes -1</td>
  </tr>
</table>


You see that the 7th user may make the value negative because it has already passed the check and moved from the if-statement when it updates the value.

## Solution — `synchronized` keyword

Luckily, the solution to this is quite simple — just use the `synchronized` keyword for the critical section. In our case, it’s the whole `consume` method. This will tell the JVM that only one thread at a time can execute the critical section.

Here is some info you need to know regarding this:

In Java, this keyword [can be used with (both static and non-static) methods and code blocks](https://stackoverflow.com/questions/2056243/java-synchronized-block-for-class):

```java
public synchronized void m1(){}
public static synchronized void m2(){}
synchronized (this) {}
synchronized (MyClass.class) {}
```

### Synched non-static method

This means that when there is an Object, for instance, `donutStorage` that has the following method:

```java
public synchronized void setDonutsNumber(int donutsNumber) {
  this.donutsNumber = donutsNumber;
}
```

***only 1 thread will be allowed to execute it (set the variable) at a time.***

### Another synched non-static method

And when there is another synchronized method in this class:

```java
public synchronized int getDonutsNumber() {
  return donutsNumber;
}
```

***another thread will not be allowed to execute it***, while the first one is executing `setDonutsNumber()`, even though this method does not depend on `setDonutsNumber()`

However, if another synchronized method is called *within a synchronized method* *or code block* it will not cause any issues and the thread executing it will freely run that method.

```java
// the thread that is executing m1 will freely get access to m2
// and execute it, even though m2 is synchronized
public synchronized void m1() {
    m2();
}
public synchronized void m2() {}
```

### Simple unsynched method

However, if there is an *unsynchronized* method in this class, for example:

```java
public void optimizeDatabase() {}
```

***multiple other threads will be allowed to execute it***

### Static synched method

In addition, if there is a *static synchronized* method in this class, for example:

```java
public static synchronized double calculateAverageDonutWeight(Donut[] donuts) {}
```

***another thread will be allowed to execute it***, even though the first one is executing `setDonutsNumber` because one of them is static and another one is non-static.

Similarly to non-static, if there is another *static synchronized* method*,* other threads will be restricted from executing it, while this one is being executed.

### Sounds overwhelming. How to understand it?

Sounds overwhelming, but in fact, this is pretty easy to understand.

A synchronized method tells the thread executing it to acquire a lock, which doesn’t allow any other threads to pass if they don’t have the lock.

By default, there are only two locks associated with a class: class-level lock (for static methods), and object-level lock (for non-static methods).

Synchronized blocks require an explicit indication of what lock they use.

```java
synchronized (this) {}						// object-level lock
synchronized (MyClass.class) {}		// class-level lock
```

There is a good visual explanation in [this video](https://youtu.be/IIgHG_YHXPE). It is also a good idea to play around with code to understand the topic and put the necessary info into your long-term memory.

### Updated code

Mind you, *in this case*, when we use `synchronized`, `AtomicInteger` is no longer needed. That’s because it’s only `consume` method that causes the race condition and no one else. Keeping `AtomicInteger` will only cause performance degradation. However, if you eventually decide to get multithreaded access to the `DonutStorage` in other parts of your code, you will need to use `synchronized` either (or find another solution).

Here’s the updated code:

```java
// DonutStorage is the same as it was in the beginning
public class DonutStorage {
    private int donutsNumber;
    public DonutStorage(int donutsNumber) {this.donutsNumber = donutsNumber;}
    public int getDonutsNumber() {return donutsNumber;}
    public void setDonutsNumber(int donutsNumber) {this.donutsNumber = donutsNumber;}
}

public int consume(int numberOfItemsToConsume) {
    synchronized (donutStorage) {
        int donutsNumber = donutStorage.getDonutsNumber();
        // if there aren't enough donuts in stock, consume as many as there are
        if (numberOfItemsToConsume > donutsNumber) {
            donutStorage.setDonutsNumber(0);
            return donutsNumber;
        }
        donutStorage.setDonutsNumber(donutsNumber - numberOfItemsToConsume);
        return numberOfItemsToConsume;
    }
}
```

You can compare the old and the updated versions [here](https://github.com/DanielRendox/ThreadSynchronizationInJava/commit/695039618cd7bc14d298c7cd58ae5b8c31ee4a40).

Also, note that making the `consume` method `synchronized` wouldn’t work. That’s because a thread entering it would have to acquire a lock for the `Consumer` object, while we want it to get a lock for the `donutStorage`.

There is no point in getting a lock for the `Consumer` object because each thread has its own `Consumer` object therefore each `Consumer` is used by only one thread. On the other hand, `donutStorage` is a single instance of the `DonutStorage` class throughout our code. Getting a lock for it before executing the `consume` method forces other threads to wait until the current one releases that lock.

Output:

```
pool-1-thread-3 consumed 0
pool-1-thread-7 consumed 3
pool-1-thread-5 consumed 3
pool-1-thread-8 consumed 3
pool-1-thread-1 consumed 3
pool-1-thread-2 consumed 3
pool-1-thread-4 consumed 2
pool-1-thread-6 consumed 3
pool-1-thread-8 consumed 0
pool-1-thread-3 consumed 0
Number of remaining donuts: 0
```

You can also add that print-random-text command to make sure that it works properly.

## `AtomicInteger` vs `synchronized`

Now you may be wondering why he told me about `AtomicInteger` if it’s easier just to use `synchronized`. 

Well, atomic classes are faster as they don’t use blocking. Not using blocking is also better for preventing deadlocks, which will be brought up in the following article. Also, when you use an atomic class and want to create another thread-safe block of code, you will not need to synch it.

However, as you saw, atomic classes don’t fully prevent race conditions. So let’s break it down to understand when to use `AtomicInteger` over `synchronized`.

`AtomicInteger` variable is an equivalent of a simple variable with synchronized getters and setters:

This:

```java
public class DonutStorage {
    private final AtomicInteger donutsNumber;
    public DonutStorage(int donutsNumber) {
        this.donutsNumber = new AtomicInteger(donutsNumber);
    }
    public AtomicInteger getDonutsNumber() {return donutsNumber;}
}
```

Will give the same result as this:

```java
public class DonutStorage {
    private int donutsNumber;
    public DonutStorage(int donutsNumber) {this.donutsNumber = donutsNumber;}
    public synchronized int getDonutsNumber() {return donutsNumber;}
    public synchronized void setDonutsNumber(int donutsNumber) {this.donutsNumber = donutsNumber;}
}
```

The code in the “[`AtomicInteger` may be not enough](#problem-3-raw-atomicinteger-endraw-may-be-not-enough)” section doesn’t work, whereas the code in “[Solution — `AtomicInteger`](#solution-raw-atomicinteger-endraw-)" works fine. That’s because the latter’s `consumer` method contains only 1 operation (atomic subtraction from the value) whereas the former’s contains as many as 4 accesses to the value.

> So, when you need to perform simple updates on the variable, `AtomicInteger` is best. But, if your synchronization scope is bigger than that use `synchronized`.
> 

In addition, I wanted to emphasize that it’s recommended to first search for some ready and well-tested solutions for your problem.

There is also a good explanation of this on [StackOverflow](https://stackoverflow.com/questions/17253260/synchronization-while-using-atomicinteger).

## Conclusion

Sorry for loading you with that amount of information. Unfortunately, multithreading is not an easy topic. You could just learn to simply use `synchronized` and that’s it, but the real problems would come in practice. I tried to provide real examples, problems, solutions to them, and common gotchas.

To sum up, race conditions are common multithreading problems that sometimes may be not easy to spot. It’s important to synchronize threads if they have access to the shared resource. Of course, atomic classes and `synchronized` aren’t the only ways to synchronize threads. The solution to your specific problem depends on the complexity of your code and what actually you want to get. It’s always better to first search for a ready solution.

Thank you for reading this article! I’m excited to write a new one in a few days. It’s going to be about inter-thread communication, particularly explaining `wait` and `notify` methods, and probably `SynchronousQueue`. If you learned something from this tutorial, please provide some feedback. If you have any questions or corrections, I would love to hear from you in the comments.

## Useful resources

Here are some useful resources that I learned from.

1. The code from this article is available on [GitHub](https://github.com/DanielRendox/ThreadSynchronizationInJava).
2. [Synchronization | GeeksforGeeks (YouTube video)](https://youtu.be/IIgHG_YHXPE) — a good visual representation of locks.
3. [Synchronization while using AtomicInteger | Stack Overflow](https://stackoverflow.com/questions/17253260/synchronization-while-using-atomicinteger) — if you didn’t understand when to use `AtomicInteger` over `synchronized`.
4. [Synchronized Block for .class | Stack Overflow](https://stackoverflow.com/questions/2056243/java-synchronized-block-for-class) — if you didn’t understand what is `synchronized (MyClass.class)`