7

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
1
  • No, side effects are bad. If you don't have state, it's much harder to have race conditions.
    – PlexQ
    Commented Mar 31, 2012 at 1:32

2 Answers 2

18

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.

5

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:

  1. read sum into a register
  2. add to the register with the sum value
  3. write the updated value back to memory

If 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.

  1. Use @volatile annotation to ensure visibility of sum when doing something like this. See here.
  2. Even with @volatile, due to the non-atomicity of the increment you will be losing some increments. You should use AtomicIntegers and their incrementAndGet.
  3. Although using atomic counters will ensure correctness, having shared variables here hinders performance greatly - your shared variable is now a performance bottleneck because every thread will try to atomically write to the same cache line. If you wrote to this variable infrequently, it wouldn't be a problem, but since you do it in every iteration, there will be no speedup here - in fact, due to cache-line ownership transfer between processors, it will probably be slower.

So, as Daniel suggested - use reduce for this.

Not the answer you're looking for? Browse other questions tagged or ask your own question.