Reputation: 18778
This is a school assignment, but I really need some help with this one. I can't for the life of me figure out why the two different versions of nextValue()
behave differently - one is thread safe and the other one is not. Can somebody give me some pointers in the right direction at least?
I've included both versions in the same class below, but obviously they're not both present in the code...
public class NumGenerator {
static final int MIN_VALUE = -256;
static final int MAX_VALUE = 255;
static final int INITIAL_VALUE = MIN_VALUE -1;
private final AtomicInteger counter = new AtomicInteger(INITIAL_VALUE);
private final AtomicInteger resetCounter = new AtomicInteger(0);
private final Object lock = new Object();
// Thread safe
public int nextValue() {
int next = counter.incrementAndGet();
if (next > MAX_VALUE) {
synchronized (lock) {
next = counter.incrementAndGet();
if (next> MAX_VALUE) {
counter.set(MIN_VALUE);
resetCounter.incrementAndGet();
next = MIN_VALUE;
}
}
}
return next;
}
// Non thread safe
public int nextValue() {
int next = counter.incrementAndGet();
if (next > MAX_VALUE) {
synchronized (lock) {
int i = counter.get();
if (i > MAX_VALUE) {
counter.set(INITIAL_VALUE);
resetCounter.incrementAndGet();
}
next = counter.incrementAndGet();
}
}
return next;
}
}
Upvotes: 0
Views: 877
Reputation: 36
Both are Thread-Safe. Maybe you can paste out the code how you are testing them. The issue might be there.
Upvotes: 0
Reputation: 5721
Let's say values were : MIN_VALUE = -1, MAX_VALUE = 3, counter = 3.
Code 1:
synchronized (lock) {
next = counter.incrementAndGet();
if (next> MAX_VALUE) {
counter.set(MIN_VALUE);
resetCounter.incrementAndGet();
next = MIN_VALUE;
}
}
if(next > MAX_VALUE)
becomes if(4>3) this would change the value of next to -1 and return it.Code 2:
synchronized (lock) {
int i = counter.get();
if (i > MAX_VALUE) {
counter.set(INITIAL_VALUE);
resetCounter.incrementAndGet();
}
next = counter.incrementAndGet();
}
i
would still be 3. if(i > MAX_VALUE)
becomes if(3 > 3), which its not so returns 3 as the output.incrementAndGet
and get
are different.
So the code with same values is returning different output.
one is incrementing the value first then checking the condition, the other is checking the values first and then performing an operation.
Even the code inside the if( variable > MAX_VALUE) would result in different output.
So this has nothing to do with Thread safety.
Upvotes: 1
Reputation: 362
Think Both methods are thread safe logically. because in both methods synchronized is used. and synchronized block is used for thread safety.
Upvotes: 0