Reputation: 1763
Hi was reading about that a string is thread safe because it is immutable.
For example i do:
String a = "test";
One thread uses this variable. But another thread could still also use this variable and change it:
a = a + "something";
So it would change or not?
If it would be volatile, i would get it, that it can just be used by one thread at a time. But immutabilty doesnt guarantee me this!?
Upvotes: 2
Views: 530
Reputation: 1
A lot of confusion here...
What thread safety of some class means is that concurrent use of it's instance will not destroy it's internal structure.
In our case it is just a warranty that we finally get a "testsomething", but not a mess like "tsomethingest" or "tesomethingst" or "tseosmtething" or "somethingtest".
Here a "quick and dirty" illustration:
public class Test2 {
private volatile String tstStr = "";
Test2(){
}
void impl(int par){
Thread wrk = new Thread(new MyRun(par));
wrk.start();
}
static public void main(String[] args) throws Exception {
Test2 tst2 = new Test2();
long startTime = System.currentTimeMillis();
Thread wrk;
for (int i = 0; i < 9; i=i+1) {
tst2.impl(i);
}
long endTime = System.currentTimeMillis();
System.out.println("The process took " + (endTime - startTime) + " milliseconds");
}
class MyRun implements Runnable {
int no;
MyRun(int var){
no = var;
}
public void run(){
tstStr = tstStr + " " + no;
for (int i = 0; i < 3; i=i+1) {
System.out.println("Message from "+no+", tested string ="+tstStr);
}
}
}
}
The output:
Message from 1, tested string = 0
Message from 1, tested string = 0 2 3
Message from 1, tested string = 0 2 3
Message from 4, tested string = 0 2 3 4
Message from 4, tested string = 0 2 3 4
Message from 0, tested string = 0 2
Message from 8, tested string = 0 2 3 4 7 8
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
The process took 0 milliseconds
Message from 7, tested string = 0 2 3 4 7
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 4, tested string = 0 2 3 4
Message from 3, tested string = 0 2 3
Message from 2, tested string = 0 2
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 8, tested string = 0 2 3 4 7 8 5
Message from 5, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 8, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6
Upvotes: 0
Reputation: 8953
Strings objects are thread-safe. If your String a
is a local variable then this code is still thread-safe. If it is a field of your class than it is your responsibility to guarantee its thread-safety. Thread-safety of String won't magically make your own code thread-safe. You should take care about it.
You can make field volatile then you get visibility among threads. So any thread will see up-to-date value of your field. But you won't get atomicity in this way. Imagine the following. Let a = "test"
. Thread 1 updates a and thread 2 updates a. They both see current value which is "test"
. They read it, make new strings by concatenation and update value of a
. And what will be that value? It is unknown. It can be "testsomethingsomething"
if threads perform their operations strictly one after another. But it can be just "testsomething"
. For instance:
"test"
from a
"test"
from a
a
with "testsomething"
a
(remember, it read a
as "test"
before) with the same "testsomething"
Voila, you've lost an update to your field. To avoid this kind of problem, you should guard all accesses and modifications to your field with synchronization on single lock object.
Upvotes: 0
Reputation: 24812
You're not changing the object pointed by a
, but where a
points to:
String a = "test";
here a
points to a string "test"
a = a + "something";
here a new string is created as the result of the concatenation of "test"
and "something"
, which "testsomething"
where a points to. It's a different instance.
So there is no problem of thread safety, as both threads will have their own a
referring to the same "test"
string object, but once one of those thread will modify the string to be referring the "testsomething"
object, the other Thread will still be referring the original "test"
object.
Upvotes: 5
Reputation: 892
The String itself isn't changing, the reference is. It sounds like you need the reference to be final. Immutability guarantees that the Object does not change, not that the reference cannot change. Just mark it like this:
final String a = "test";
Upvotes: 2
Reputation: 545588
You can make the code thread safe trivially by having each thread copy the reference a
. In fact, that’s normally what happens anyway, since you usually pass the string to the thread via a parameter.
So both threads hold a reference to the original string, here "test"
. If thread 1 now modifies a
it only modifies this reference. Thread 2 still retains an intact reference to "test"
because the string itself (rather than the reference) is immutable.
Upvotes: 0