Reputation: 39
I'm just studying for an exam and I have the following non thread-safe code from a previous exam question:
class Q3 {
private boolean f[] = new boolean[20];
public Q3() {
for (int j = 0; j < 20; j++) {
f[j] = true;
}
}
public void negate(int a, int b) {
for(int j = a; j < b; j++) {
f[j] = !f[j];
}
}
public void swap(int a, int b) {
boolean temp = f[a];
f[a] = f[b];
f[b] = temp;
}
}
I made it thread safe by making the following adjustments:
class Q3 {
private boolean f[] = new boolean[20];
public Q3() {
for (int j = 0; j < 20; j++) {
f[j] = true;
}
}
synchronized void negate(int a, int b) {
for (int j = a; j < b; j++) {
f[j] = !f[j];
}
}
synchronized void swap(int a, int b) {
boolean temp = f[a];
f[a] = f[b];
f[b] = temp;
}
}
But could somebody explain to me why the original code is not thread safe? I know how to make code thread safe once it isn't so, but i'm still unsure as to why code is/is not defined as being thread safe
Upvotes: 2
Views: 118
Reputation: 2055
Let us say 2 threads simultaneously calls negate and swap respectively and all index have value true initially. Now lets say both thread reads the value=true in 4th index at same time. 1st thread calls negate and its negating the 4th element making it false, at same time 2nd thread read the 4th element and swaps to 5th element which is true. So the end result in this case would be 4th index value = false 5th index value = true.
Now since we can't predict the execution order their can be another execution scenario. Thread 1 reads 4th element makes it to false then thread 2 reads the value after thread 1 updates, so reads it as false and swaps this value with 5th element. So in this case end result would be 4th Index value= true and 5th index = false So, bottom line, if we don't make it synchronize we can't predict thread execution order and might get unexpected result. So, when you say synchronize, these 2 methods would never be called together and hence its not possible to read/write same index element at same time by multiple threads.
Upvotes: 1
Reputation: 522626
This answer assumes that multiple threads may be acting on the same instance of a Q3
object. Taking the swap()
method as an example:
public void swap(int a, int b) {
boolean temp = f[a];
f[a] = f[b];
f[b] = temp;
}
If two separate threads were to both call swap()
and interleave, the following could happen:
Thread one:
boolean temp = f[a];
f[a] = f[b];
Thread two:
boolean temp = f[a]; // his temp = f[b], wrong!
Thread one:
f[b] = temp; // f[b] = f[b], no swap!
Thread two:
f[a] = f[b];
f[b] = temp; // f[a] = f[b], wrong
The end result of this is that both f[a]
and f[b]
end up with the value of the latter, for both threads, which clearly isn't what you want. By making the swap()
method synchronized
, you ensure that a given thread will execute that method atomically, i.e. a given thread will either complete the entire method alone, or will not, with nothing in between.
Upvotes: 2