2012-03-30 21 views
6

¿Las colecciones paralelas están destinadas a realizar operaciones con efectos secundarios? Si es así, ¿cómo puedes evitar las condiciones de carrera? Por ejemplo:cómo evitar las condiciones de carrera con scala parallel collections

var sum=0 
(1 to 10000).foreach(n=>sum+=n); println(sum) 

50005000 

ningún problema con esto. Pero si tratar de establecer paralelismos, las condiciones de carrera suceda:

var sum=0 
(1 to 10000).par.foreach(n=>sum+=n);println(sum) 

49980037 
+0

No, los efectos secundarios son malos. Si no tiene estado, es mucho más difícil tener condiciones de carrera. – PlexQ

Respuesta

17

respuesta rápida: no hagas eso. El código paralelo debe ser paralelo, no concurrente.

Mejor respuesta:

val sum = (1 to 10000).par.reduce(_+_) // depends on commutativity and associativity 

Ver también aggregate.

4

caso paralelo no funciona porque no utiliza las variables volátiles, por lo tanto no garantizar la visibilidad de sus escrituras y porque tiene múltiples hilos que hacer lo siguiente:

  1. leer sum en un registro
  2. añadir al registro con el valor sum
  3. escribir el valor actualizado de nuevo en la memoria

si 2 hilos de realizar el paso 1 primero o Después de la otra y luego continúe con el resto de los pasos anteriores en cualquier orden, terminarán sobrescribiendo una de las actualizaciones.

  1. Uso @volatile anotación para asegurar la visibilidad del sum cuando se hace algo como esto. Ver here.
  2. Incluso con @volatile, debido a la falta de atomicidad del incremento perderá algunos incrementos. Debe usar AtomicInteger sy su incrementAndGet.
  3. Aunque el uso de contadores atómicos garantizará su corrección, tener variables compartidas aquí dificulta enormemente el rendimiento: su variable compartida ahora es un cuello de botella de rendimiento porque cada hilo intentará escribir atómicamente a la misma línea de caché. Si escribió esta variable con poca frecuencia, no sería un problema, pero como lo hace en cada iteración, no habrá aceleración aquí; de hecho, debido a la transferencia de la propiedad de la línea de caché entre los procesadores, probablemente será más lenta. .

Así que, como Daniel sugirió, use reduce para esto.

Cuestiones relacionadas