Wednesday, October 24, 2018

String And Thread-Safety in Java

We do know that String objects are immutable. It is also true that immutable objects are thread-safe so by transitive law string objects are thread-safe. In this post let’s go a little deeper into this question of Is String thread safe in Java.

To understand whether String in Java is thread safe or not first let’s understand these two terms; Immutable object and thread safety-

Immutable object- An immutable object is an object that would not be able to change its state after creation. Thus immutable object can only be in one state and that state can not be changed after creation of the object.

Thread safety– I’ll quote “Java concurrency in practice” book here– A class is thread-safe if it behaves correctly when accessed from multiple threads, where correctness means that a class conforms to its specification.

Thread safety in String

String in Java, being immutable, has the specification that the Strings are constant; their values cannot be changed after they are created. 

But there is a little confusion with many users when it comes to this question Is String thread safe in Java. Many people think that string is immutable so thread safety here should mean even if multiple threads are accessing the same string those threads should not be able to change the content of the string at all as the String being immutable can't be modified.

But threads can change the content main point here is in that case reference of that string will also change.
Whenever content of the String is changed, a new String is created and the reference is changed. Same thing will happen in case of multiple threads too.

Java String thread safe example

Let’s try to see this with an example. In this example three threads are created and all of them share the same string object. In each of these thread, thread name is appended to the string and then that string is printed. Thread class' join() method is also used here to wait for all of the threads to finish and then the string object is printed again.

public class StrThread implements Runnable {
    private String s;
    //Constructor
    public StrThread(String s){
        this.s = s;
    }
    @Override
    public void run() {
        System.out.println("in run method " + Thread.currentThread().getName());        
            
            try {
                // introducing some delay
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }  
            // Adding to String  
            s = s + Thread.currentThread().getName();
            System.out.println("String " + s);
    }
    
    public static void main(String[] args) {
        String str = "abc";
        // Three threadss
        Thread t1 = new Thread(new StrThread(str));
        Thread t2 = new Thread(new StrThread(str));
        Thread t3 = new Thread(new StrThread(str));
        t1.start();
        t2.start();
        t3.start();
        // Waiting for all of them to finish
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {    
            e.printStackTrace();
        }
        System.out.println("String is " + str.toString());
    }
}

Output

in run method Thread-0
in run method Thread-1
in run method Thread-2
String abcThread-1
String abcThread-2
String abcThread-0
String is abc

Here note that every thread changes the content of the string but in the process where str refers to is also changed, so effectively each thread gets its own string object. Once all the threads finish, str is printed in the main method again and it can be seen that the original string is printed meaning original reference with the original content remains intact.

With this program you can see that String is immutable so original String won't be changed but String reference can still be changed with multiple threads. So Java Strings are thread safe here means when the shared String is changed it creates a new copy for another thread that way original String remains unchanged.

To see what may happen with a mutable object let us use StringBuffer in the place of String.

public class StrThread implements Runnable {
    private StringBuffer s;
    //Constructor
    public StrThread(StringBuffer s){
        this.s = s;
    }
    @Override
    public void run() {
        System.out.println("in run method " + Thread.currentThread().getName());        
            
            try {
                // introducing some delay
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    
            s.append(Thread.currentThread().getName());
            System.out.println("String " + s);
    }
    
    public static void main(String[] args) {
        StringBuffer str = new StringBuffer("abc");
        // Three threadss
        Thread t1 = new Thread(new StrThread(str));
        Thread t2 = new Thread(new StrThread(str));
        Thread t3 = new Thread(new StrThread(str));
        t1.start();
        t2.start();
        t3.start();
        // Waiting for all of them to finish
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {    
            e.printStackTrace();
        }
        System.out.println("String is " + str.toString());
    }
}

Output

in run method Thread-0
in run method Thread-1
in run method Thread-2
String abcThread-0
String abcThread-0Thread-2
String abcThread-0Thread-2Thread-1
String is abcThread-0Thread-2Thread-1

Note – output may vary in different runs

Here it can be seen that shared StringBuffer object is modified.

That's all for this topic String And Thread-Safety in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related topics

  1. String in Java
  2. String Comparison in Java
  3. Splitting a String Using split() Method in Java
  4. StringBuilder in Java
  5. Java String Interview Questions

You may also like-

  1. Inter-thread communication using wait, notify and notifyAll
  2. Deadlock in Java multi-threading
  3. interface default methods in Java 8
  4. effectively final in Java 8
  5. BlockingQueue in Java Concurrency
  6. Callable and Future in Java concurrency
  7. Access modifiers in Java
  8. Difference Between Checked & Unchecked Exception in Java

1 comment:

  1. thank you for sharing such a nice and interesting blog with us. i have seen that all will say the same thing repeatedly. But in your blog, I had a chance to get some useful and unique information. I would like to suggest your blog in my dude circle. please keep on updates. hope it might be much useful for us. keep on updating...
    Software Testing Training

    ReplyDelete