Reputation: 671
The author of this page mentions that the second code example below suffers from a synchronization problem but the code will work about 99 times in 100. I am not able to see the operational difference in the two programs in that page.
A somewhat more general solution that combines the previous two is to copy the value of the field into a local variable, then change only the local variable. The field remains unchanged inside the method. For example,
public class Counter {
int count = 0;
public void count() {
int count = this.count;
int limit = count + 100;
while (count++ != limit) System.out.println(count);
}
}
Note how the local variable count shadows the field count, and how the this keyword is used to refer to the field count outside the shadow.
This trick is primarily useful when you don't need to save the changed variable back into the field when the method is done. The following saves the state, but is still subject to less obvious synchronization problems.
public class Counter {
private int count = 0;
public void count() {
int count = this.count;
int limit = count + 100;
while (count++ != limit) System.out.println(count);
this.count = count;
}
}
In fact, this is probably even worse than the original example because it will work 99 times out of a 100. The bug here is extremely hard to pin down if you don't spot it in the source code.
Upvotes: 2
Views: 78
Reputation: 881553
The problem lies with the fact that the modification to this.count
is not atomic.
Let's say two threads are calling this function and this.count
is currently set to 0
.
Thread 1 loads 0
into its local count
and then starts incrementing it to 101
(not 100
as previously thought since it increments count
one more time after the limit is reached, with count++ != limit
).
In the meantime, thread 2 comes in and this.count
is still set to 0
so it grabs it and starts incrementing to 101
.
At some point, they then both reach the line this.count = count
(and the order doesn't matter) and they both set this.count
to 101.
What it should have been set to at the end was 202
(I think - certainly it should be around the 200
mark somewhere).
The reason the first bit of code is valid is because it's not actually trying to change the this.count
value hence no race condition is possible.
Upvotes: 2