Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is Thread Safe in Java?
3.
Why do we Need Thread safe in Java?
3.1.
Multithreading
3.2.
Race Condition in Multithreading
4.
How to Achieve Thread Safety in Java?
4.1.
Using Final Keyword
4.2.
Using Volatile Keyword
4.3.
Using Synchronization
4.4.
Using Atomic Variable
5.
Thread Safe Classes in Java
6.
Important Points About Thread-Safety in Java
7.
Frequently Asked Questions
7.1.
Why StringBuffer is thread-safe?
7.2.
How can we achieve thread safe in Java?
7.3.
What are Thread Safe Classes in Java?
8.
Conclusion
Last Updated: Mar 27, 2024
Medium

Thread Safe in Java

Author Jay Dhoot
1 upvote
Crack Google SDE interview : Essential projects
Speaker
Saurav Prateek
SDE-2 @
20 Jun, 2024 @ 01:30 PM

Introduction

Do you know that multiple threads executing multiple threads simultaneously can lead to data inconsistency in Java?

Thread Safe in JAVA

Thread safe in Java is a way to prevent data inconsistency by preventing another thread from working on the same object while a thread is working on it. In this article, we will learn about thread-safe in Java. We will also discuss achieving thread-safe in Java and thread-safe classes in Java.  

Also read, even number program in java 

What is Thread Safe in Java?

Preventing another thread from working on the same object while a thread is working on it is called Thread Safe in Java. A data structure is termed thread-safe when multiple threads can perform operations concurrently without involving the risk of race conditions. 

When a thread performs some action on a particular object, no other thread should be allowed to delete or modify the object.

Also see,  Eclipse ide for Java Developers

Get the tech career you deserve, faster!
Connect with our expert counsellors to understand how to hack your way to success
User rating 4.7/5
1:1 doubt support
95% placement record
Akash Pal
Senior Software Engineer
326% Hike After Job Bootcamp
Himanshu Gusain
Programmer Analyst
32 LPA After Job Bootcamp
After Job
Bootcamp

Why do we Need Thread safe in Java?

Before diving into thread safety in Java, Let’s first understand Multithreading and Race condition in Multithreading.

Multithreading

Java supports Multithreading, meaning that multithreaded programs can be developed using Java. Multithreading is the process of executing multiple threads concurrently or simultaneously.

A thread is the fundamental/smallest unit of processing. Threads are lightweight sub-processes that use a shared memory area. Several threads can run within a single program.

In simple words, a multithreaded program has two or more parts(called ‘threads’) that can run simultaneously and perform different tasks at the same time.

Race Condition in Multithreading

As multiple threads use the same data resources, it might be possible that one thread interrupts another thread’s read operation for its own delete or update operation. 

A race condition occurs when two or more threads access the critical section. A critical section is that part of a program where shared memory is accessed.
 

Consider a scenario where two threads update the same integer variable, ‘counter.’

Race Condition

Clearly, both threads read the value, decrement it and then update the variable counter. But as we can see, Thread C could access the data value before Thread N updates the counter variable, leading to inconsistent results. We expected two separate decrements by both the threads, i.e., the final value of the counter variable was expected to be 0, but instead, we got it as 1. This scenario is a typical example of race condition.

Thready Safe in Java is needed to prevent race conditions as it leads to inconsistency because of unsyncronization of multiple threads executing at the same time.

How to Achieve Thread Safety in Java?

There are many ways to achieve Thread Safety in Java:

Using Final Keyword

Final variables are thread-safe as once they are assigned with some reference of an object, they can not modify or point to the reference of another object. For example,

Code

public class Main
{
    // Variable int of type final
    final int c = 1;
    
    void method()
    {
        //Will throw an error as value of 
        //final Variable can not be changed once assigned
        c = 5;
    }
}


Output

Output

 

Using Volatile Keyword

It is a field modifier that allows multiple threads to use the instance and method of the classes simultaneously without any problem. It doesn't cache the variable's value and always reads it from the main memory. For example,

Code

public class Main
{
    // Creating a volatile variable count
    static volatile int count=0;
 
    // Static method 
    static void increment()
    {
        count=count+1;
    }
 
    // Static method
    static void show()
    {
        System.out.println(
            "count=" + count);
    }
    
public static void main(String[] args)
{
    //Creating Thread a
Thread a = new Thread()
{
            public void run()
            {
                for (int j = 0; j < 3; j++)
                {
                    increment();
                }
            }
        };
 
        // Creating Thread b
        Thread b = new Thread()
        {
            public void run()
            {
                for (int j = 0; j < 3; j++)
                {
                   show(); 
                }
            }
        };
 
        // Executing the Threads simultaneously 
        a.start();
        b.start();
}
}


Output

Output

Using Synchronization

Synchronization allows only one thread at a time to complete a particular task. Java provides a method of synchronizing its task using synchronized blocks, which synchronize on some objects. It uses the synchronized keyword. All synchronized blocks are synchronized on the same object, with only one thread running inside them at a time. These synchronized blocks of code are called a critical section which prevents all other threads from attempting to enter inside it until the thread inside the synchronized block is done with its execution and has left the critical section. For example,

Code

class C {
    synchronized void sync(int n)
    {
 
        // Creating a thread instance
        Thread t = Thread.currentThread();
        String s = new String(t.getName());
        System.out.println("Only "+s+ " is inside synchronized block");
        for (int i = 1; i <= 5; i++) {
            System.out.println(s + " : " + (n*i));
        }
        
        System.out.println("Execution of "+s+ " is complete");
        System.out.println();
    }
}


class N extends Thread {
 
    C a = new C();
    public void run()
    {
 
        // Calling sync method
        a.sync(1);
    }
}
public class Main
{
    public static void main(String[] args)
    {
 
        // Creating an object of class N
        N b = new N();
 
        // Initializing Thread s1
        Thread s1 = new Thread(b);
 
        // Initializing Thread s2
        Thread s2 = new Thread(b);
 
        // Setting names of Thread
        s1.setName("Thread Coding");
        s2.setName("Thread Ninjas");
 
        // Executing the Threads simultaneously 
        s1.start();
        s2.start();
    }
}


Output

Output


Also see, Java Ioexception

Using Atomic Variable

Atomic variables ensure that when multiple threads share the same variable, only one thread can access and modify the variable at a time. For example,

Code

import java.util.concurrent.atomic.AtomicInteger;
class Count {
 
    // Variable of class type Atomic Integer
    AtomicInteger num= new AtomicInteger();
 
    // Increment Method
    public void increment()
    {
        num.addAndGet(1);
    }
}

public class Main
{
    public static void main(String[] args) throws Exception
    {
 
        // Creating an object of class Count
        Count c = new Count();
 
        // Creating Thread a
        Thread a = new Thread
        (
            new Runnable() 
            {
                public void run()
                {
                    for (int i = 1; i <= 5; i++) {
                        c.increment();
                    }
                }
            }
        );
 
        // Creating Thread b
        Thread b = new Thread
        (
            new Runnable() 
            {
                public void run()
                {
                    for (int i = 1; i <= 5; i++) {
                        c.increment();
                    }
                }
            }
        );
 
        // Executing the Threads simultaneously 
        a.start();
        b.start();
 
        // Calling join method on Thread a and Thread b
        a.join();
        b.join();
 
        System.out.println("Value of num after updation by both threads is " +c.num);
    }
}


Output

Output

Thread Safe Classes in Java

Thread Safe Classes are designed so that multiple threads can use them concurrently without causing data inconsistency, data races, and other concurrency-related issues. These classes guarantee that their internal structure is maintained consistently and all operations on the class objects are properly synchronized and executed atomically.

Some of the thread-safe classes in Java are HashtableStackVector, etc.

Important Points About Thread-Safety in Java

Thread safety in Java is necessary to prevent conflicts when multiple threads access shared resources concurrently. 

  • Concurrent Access: When several threads access data or objects simultaneously, it can lead to issues like data corruption or unexpected behavior.
     
  • Immutable Objects: Immutable objects, once created, cannot be changed. They are inherently thread-safe because they eliminate the need for synchronization.
     
  • For safe concurrent operations, Java offers thread-safe classes like ConcurrentHashMap and AtomicInteger.
     
  • Volatile Keyword: The volatile keyword ensures the visibility of variable changes across threads, enhancing thread safety.
     
  • Avoiding Race Conditions: Identifying and avoiding race conditions is crucial to maintain thread safety.
     
  • Deadlocks: Careful coding is essential to prevent deadlocks, where threads wait indefinitely for each other.
     
  • Concurrency Utilities: Java's java.util.concurrent package provides high-level concurrency utilities for more accessible thread-safe programming.
    Read more, how to run java program

Frequently Asked Questions

Why StringBuffer is thread-safe?

StringBuffer is thread-safe because it's designed to handle multiple threads safely. It locks parts of its operations to prevent conflicts when different threads access it simultaneously.

How can we achieve thread safe in Java?

Thread safe in Java can be achieved by using final keyword, using volatile keyword, using synchronization and using atomic variables.

What are Thread Safe Classes in Java?

Thread Safe Classes are designed so multiple threads can use them concurrently without causing data inconsistency, data races, and other concurrency-related issues. These classes guarantee that their internal structure is maintained consistently and all operations on the class objects are properly synchronized and executed atomically.

Conclusion

In this article, we have discussed thread safe in Java. To learn more about multithreading, you can refer to the below-mentioned article:

Multithreading in Java

Multithreading in Python

We hope this article has helped you understand thread safe in Java. If this article helped you in any way, then you can read more such articles on our platform, Coding Ninjas Studio. You will find articles on almost every topic on our platform. Also, for cracking good product-based companies, you can practise coding questions at Coding Ninjas. For interview preparations, you can read the Interview Experiences of popular companies.
 

Happy Coding !!

Previous article
Fibonacci Series in Java
Next article
How to Run Java Program?
Live masterclass