Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Browser testing is essential if you have a website or web applications that users interact with. Manual testing can be very helpful to an extent, but given the multiple browsers available, not to mention versions and operating system, testing everything manually becomes time-consuming and repetitive.

To help automate this process, Selenium is a popular choice for developers, as an open-source tool with a large and active community. What's more, we can further scale our automation testing by running on theLambdaTest cloud-based testing platform.

Read more through our step-by-step tutorial on how to set up Selenium tests with Java and run them on LambdaTest:

>> Automated Browser Testing With Selenium

Partner – Orkes – NPI EA (cat=Java)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

eBook – Java Concurrency – NPI (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

1. Overview

While the volatile keyword in Java usually ensures thread safety, it’s not always the case.

In this tutorial, we’ll look at the scenario when a shared volatile variable can lead to a race condition.

2. What Is a volatile Variable?

Unlike other variables, volatile variables are written to and read from the main memory. The CPU does not cache the value of a volatile variable.

Let’s see how to declare a volatile variable:

static volatile int count = 0;

3. Properties of volatile Variables

In this section, we’ll look at some important features of volatile variables.

3.1. Visibility Guarantee

Suppose we have two threads, running on different CPUs, accessing a shared, non-volatile variable. Let’s further suppose that the first thread is writing to a variable while the second thread is reading the same variable.

Each thread copies the value of the variable from the main memory into its respective CPU cache for performance reasons.

In the case of non-volatile variables, the JVM does not guarantee when the value will be written back to the main memory from the cache.

If the updated value from the first thread is not immediately flushed back to the main memory, there’s a possibility that the second thread may end up reading the older value.

The diagram below depicts the above scenario:

Volatile Variable

Here, the first thread has updated the value of the variable count to 5. But, the flushing back of the updated value to the main memory does not happen instantly. Therefore, the second thread reads the older value. This can lead to wrong results in a multi-threaded environment.

On the other hand, if we declare count as volatile, each thread sees its latest updated value in the main memory without any delay.

This is called the visibility guarantee of the volatile keyword. It helps in avoiding the above data inconsistency issue.

3.2. Happens-Before Guarantee

The JVM and the CPU sometimes reorder independent instructions and execute them in parallel to improve performance.

For example, let’s look at two instructions that are independent and can run simultaneously:

a = b + c;
d = d + 1;

However, some instructions can’t execute in parallel because a latter instruction depends on the result of a prior instruction:

a = b + c;
d = a + e;

In addition, reordering of independent instructions can also take place. This can cause incorrect behavior in a multi-threaded application.

Suppose we have two threads accessing two different variables:

int num = 10;
boolean flag = false;

Further, let’s assume that the first thread is incrementing the value of num and then setting flag to true, while the second thread waits until the flag is set to true. And, once the value of flag is set to true, the second thread reads the value of num.

Therefore, the first thread should execute the instructions in the following order:

num = num + 10;
flag = true;

But, let’s suppose the CPU reorders the instructions as:

flag = true;
num = num + 10;

In this case, as soon as the flag is set to true, the second thread will start executing. And because the variable num is not yet updated, the second thread will read the old value of num, which is 10. This leads to incorrect results.

However, if we declare flag as volatile, the above instruction reordering would not have happened.

Applying the volatile keyword on a variable prevents instruction reordering by providing the happens-before guarantee.

This ensures that all instructions before the write of the volatile variable are guaranteed not to be reordered to occur after it. Similarly, the instructions after the read of the volatile variable cannot be reordered to occur before it.

4. When Does the volatile Keyword Provide Thread Safety?

The volatile keyword is useful in two multi-threading scenarios:

  • When only one thread writes to the volatile variable and other threads read its value. Thus, the reading threads see the latest value of the variable.
  • When multiple threads are writing to a shared variable such that the operation is atomic. This means that the new value written does not depend on the previous value.

5. When Does volatile Not Provide Thread Safety?

The volatile keyword is a lightweight synchronization mechanism.

Unlike synchronized methods or blocks, it does not make other threads wait while one thread is working on a critical section. Therefore, the volatile keyword does not provide thread safety when non-atomic operations or composite operations are performed on shared variables.

Operations like increment and decrement are composite operations. These operations internally involve three steps: reading the value of the variable, updating it, and then, writing the updated value back to memory.

The short time gap in between reading the value and writing the new value back to the memory can create a race condition. Other threads working on the same variable may read and operate on the older value during that time gap.

Moreover, if multiple threads are performing non-atomic operations on the same shared variable, they may overwrite each other’s results.

Thus, in such situations where threads need to first read the value of the shared variable to figure out the next value, declaring the variable as volatile will not work.

6. Example

Now, we’ll try to understand the above scenario when declaring a variable as volatile is not thread-safe with the help of an example.

For this, we’ll declare a shared volatile variable named count and initialize it to zero. We’ll also define a method to increment this variable:

static volatile int count = 0;

void increment() {
    count++;
}

Next, we’ll create two threads t1 and t2. These threads call the above increment operation a thousand times:

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        for(int index=0; index<1000; index++) {
            increment();
        }
    }
});

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        for(int index=0; index<1000; index++) {
            increment();
        }
    }
});

t1.start();
t2.start();

t1.join();
t2.join();

From the above program, we may expect that the final value of the count variable will be 2000. However, every time we execute the program, the result will be different. Sometimes, it will print the “correct” value (2000), and sometimes it won’t.

Let’s look at two different outputs that we got when we ran the sample program:

value of counter variable: 2000 value of counter variable: 1652

The above unpredictable behavior is because both the threads are performing the increment operation on the shared count variable. As mentioned earlier, the increment operation is not atomic. It performs three operations – read, update, and then write the new value of the variable to the main memory. Thus, there’s a high chance that interleaving of these operations will occur when both t1 and t2 are running simultaneously.

Let’s suppose t1 and t2 are running concurrently and t1 performs the increment operation on the count variable. But, before it writes the updated value back to the main memory, thread t2 reads the value of the count variable from the main memory. In this case, t2 will read an older value and perform the increment operation on the same. This may lead to an incorrect value of the count variable being updated to the main memory. Thus, the result will be different from what is expected – 2000.

7. Conclusion

In this article, we saw that declaring a shared variable as volatile will not always be thread-safe.

We learned that to provide thread safety and avoid race conditions for non-atomic operations, using synchronized methods or blocks or atomic variables are both viable solutions.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook – Java Concurrency – NPI (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook Jackson – NPI EA – 3 (cat = Jackson)