I'm trying to play with ForkJoinFramework. I know that my code might not be a good use case to use ForkJoin, but it should work at least..
I'm using RecursiveAction to concurrently modify a static AtomicLong variable. But I'm having some issues there, the result is not correct and not consistent.(Everytime I run it, the result is different).
I'm assuming AtomicLong is thread-safe, so the only thing that might be a reason would be some tasks are lost. But why?
`
public class ForkJoinFramework {
private static AtomicLong sum = new AtomicLong(0);
static class MyTask extends RecursiveAction {
private static final long serialVersionUID = 1L;
int left;
int right;
MyTask(int left, int right) {
this.left = left;
this.right = right;
}
@Override
protected void compute() {
if(right - left < 100) {
for(int i = left; i < right; i++) {
sum.getAndIncrement();
}
} else {
ForkJoinTask<Void> leftTask = new MyTask(left, left + (right - left) / 2).fork();
ForkJoinTask<Void> rightTask = new MyTask(left + (right - left) / 2 + 1, right).fork();
leftTask.join();
rightTask.join();
}
}
}
public static void main(String[] args) {
MyTask myTask = new MyTask(0, 10000000);
myTask.compute();
System.out.println("Sum is: " + sum.get());
}
}
`
You have an off-by-one error. In your
forloop, you are not counting the value ofright, so if e.g.leftis 101 andrightis 150, you increment only 49 times.The value I consistently get is
9868929, because you must be splitting the task into separateForkJoinTasks10000001-9868929, or131072, or 217, which makes sense as a power of 2 based on your algorithm.Change
to
and you'll get
10000001, and if you want10000000, start with1instead of0.There's nothing wrong with losing tasks or the consistency of
AtomicLong; you just had an off-by-one error.