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. So, if you are asked the question "Is String Thread Safe in Java?",
the short answer is yes.
But let’s go deeper into why this holds true. To understand whether String in Java is thread-safe, we first need to break down
two key concepts: immutability and thread safety.
Immutable object- An immutable object is one whose state cannot be modified 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 its values are constant and cannot be changed once 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.
In reality, immutability ensures that no thread can ever change the content of an existing String. Any operation that
appears to modify a String—such as concatenation, replacement, or substring- actually creates a new String object. The reference
is updated to point to this new object, while the original remains unchanged.
So even in a multi-threaded environment, if several threads are working with the same String, they are all safely accessing
an immutable value. If one thread performs an operation that "changes" the string, it simply receives a new reference, leaving
the original untouched. This behavior guarantees that String in Java is inherently thread-safe.
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's value remains unchanged 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 Is String Thread Safe in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related topics
-
String in Java Tutorial
- String Comparison in Java equals(), compareTo(), startsWith() Methods
-
Java trim(), strip() - Removing Spaces From String
-
StringBuilder Class in Java With Examples
-
Java String Interview Questions And Answers
You may also like-
- Inter-thread Communication Using wait(), notify() And notifyAll() in Java
-
Deadlock in Java Multi-Threading
-
Interface Default Methods in Java
- Effectively Final in Java 8
-
Java BlockingQueue With Examples
-
Callable and Future in Java With Examples
- Access Modifiers in Java - Public, Private, Protected and Default
- Try-With-Resources in Java With Examples