public class PlusPlusOperatorThreadSaftey {
@Test
public void testThreadSaftey() throws InterruptedException {
class IntegerHolder {
private volatile int value = 0;
private void increase() {
value++;
}
private int getValue() {
return value;
}
}
final IntegerHolder integerHolder = new IntegerHolder();
final int numberOfIncreasePerThread = 50;
final int numberOfThreads = 100;
ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
threadPool.submit(new Runnable() {
public void run() {
for (int i = 0; i < numberOfIncreasePerThread; i++) {
integerHolder.increase();
}
}
});
}
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
assertEquals(integerHolder.getValue(), numberOfIncreasePerThread *
numberOfThreads);
}
}
When running this code on my dual core CPU sometimes the test case passes, and sometimes I get:java.lang.AssertionError: expected:<4998> but was:<5000>. Thus, the ++ operator is not atomic and updates can be lost.To fix this you could add a synchronized block, but a better approach is to use an AtomicInteger like this:
class IntegerHolder {
private AtomicInteger value = new AtomicInteger(0);
private void increase() {
value.incrementAndGet();
}
private int getValue() {
return value.get();
}
}