Reputation: 133
Are parallel collections intended to do operations with side effects? If so, how can you avoid race conditions? For example:
var sum=0
(1 to 10000).foreach(n=>sum+=n); println(sum)
50005000
no problem with this. But if try to parallelize, race conditions happen:
var sum=0
(1 to 10000).par.foreach(n=>sum+=n);println(sum)
49980037
Upvotes: 7
Views: 800
Reputation: 32335
Parallel case doesn't work because you don't use volatile variables hence not ensuring visibility of your writes and because you have multiple threads that do the following:
sum
into a registersum
valueIf 2 threads do step 1 first one after the other and then proceed to do the rest of the steps above in any order, they will end up overwriting one of the updates.
@volatile
annotation to ensure visibility of sum
when doing something like this. See here.@volatile
, due to the non-atomicity of the increment you will be losing some increments. You should use AtomicInteger
s and their incrementAndGet
.So, as Daniel suggested - use reduce
for this.
Upvotes: 5
Reputation: 297155
Quick answer: don't do that. Parallel code should be parallel, not concurrent.
Better answer:
val sum = (1 to 10000).par.reduce(_+_) // depends on commutativity and associativity
See also aggregate
.
Upvotes: 18