I am testing the use of the class AtomicInteger
but increments doesn't seem to be applied under mutual exclusion control.
Here's my test:
static class AtomicIntegerRunnable implements Runnable
{
private static AtomicInteger x;
AtomicIntegerRunnable() {}
AtomicIntegerRunnable(AtomicInteger x)
{
this.x = x;
}
@Override
public void run()
{
System.out.println(x.get());
x.getAndIncrement();
}
}
public static void main(String[] args) {
ExecutorService e = Executors.newFixedThreadPool(n_whatever);
AtomicInteger x = new AtomicInteger();
int n = 10;
for (int i=0; i<n; i++) {
e.submit(new AtomicIntegerRunnable(x));
}
e.shutdown();
while (!e.isTerminated());
}
In the print I am getting something like
0 0 1 1 1 5 4 3 2 6
instead of
0 1 2 3 4 5 6 7 8 9
. What's wrong?
EDIT for @Louis Wasserman
static class AtomicIntegerRunnable implements Runnable
{
private AtomicInteger x;
AtomicIntegerRunnable() {}
AtomicIntegerRunnable(AtomicInteger x)
{
this.x = x;
}
@Override
public void run()
{
x.getAndIncrement();
}
}
public static void main(String[] args)
{
ExecutorService e = Executors.newFixedThreadPool(n_whatever);
AtomicIntegerRunnable x = new AtomicIntegerRunnable(new AtomicInteger());
int n = 10;
for (int i=0; i<n; i++)
e.submit(x);
e.shutdown();
while (!e.isTerminated());
}
You are getting it and incrementing it in two separate actions. You are printing out the first, which makes your own code non-atomic.
Each AtomicInteger operation is atomic on its own, but you cannot use two in sequence and consider the combination atomic -- by defintion, two operations are not atomic.
To fix this:
@Override
public void run()
{
System.out.println(x.getAndIncrement());
}
However, as pointed out in the comments, you have a third action, the printing. This is also not atomic with the increment action. So, you would need to synchronize the two in order to make your list print out in order.
You could call that method printAndIncrement
.
Usually AtomicInteger is used more to ensure that multithreaded code never accidentally operates on the same integer, not to ensure that an external system (like an output buffer) sees those increments in order (because you still need something else to synchronize communication with that external system).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With