2011-01-26 12 views
5

Brian Goetz's escribió un buen artículo sobre fork-join en http://www.ibm.com/developerworks/java/library/j-jtp03048.html. En él, enumera un algoritmo de ordenación por fusión que utiliza el mecanismo de unión por horquilla, en el que realiza el ordenamiento en dos lados de una matriz en paralelo, y luego fusiona el resultado.Visibilidad de la memoria en Fork-join

El algoritmo se ordena en dos secciones diferentes de la misma matriz al mismo tiempo. ¿Por qué no se necesita una AtomicIntegerArray o algún otro mecanismo para mantener la visibilidad? ¿Qué garantía hay de que un hilo vea las escrituras hechas por el otro, o es un error sutil? Como seguimiento, ¿el ForkJoinScheduler de Scala también hace esta garantía?

Gracias!

+0

Están funcionando en diferentes secciones de la matriz. No hay disputa hasta que se trata de fusionarse. –

+3

Acepto que operan en diferentes secciones. Pero la semántica del modelo de memoria de Java dice más o menos que no todos los hilos tienen la garantía de ver todas las escrituras (a menos que la variable sea volátil). De acuerdo con este blog: http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html incluso el uso de una volátil int [] no es suficiente para garantizar que otros subprocesos vean tus escrituras en la matriz –

Respuesta

5

La unión (de ForkJoin) en sí misma requiere un punto de sincronización, esa es la información más importante. Un punto de sincronización asegurará que todas las escrituras que suceden sean visibles después de dicho punto.

Si echa un vistazo al código, puede ver dónde se produce el punto de sincronización. Esta es sólo una llamada al método invokeAll

public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) { 
    t2.fork(); 
    t1.invoke(); 
    t2.join(); 
} 

Aquí se bifurca en otro proceso t2, t1 ejecuta su tarea y que llamar hilo esperará en t2.join(). Al pasar t2. Todas las escrituras en t1 y t2 serán visibles.

Editar: Esta edición es solo para dar un poco más de una explicación de lo que quiero decir con el punto de sincronización.

supongamos que usted tiene dos variables

int x; 
volatile int y; 

Cuando se escribe a y todas las escrituras que ocurrieron antes de leer y estarán disponibles. Por ejemplo

public void doWork(){ 
    x = 10; 
    y = 5; 
} 

Si otro hilo lee y = 5 ese hilo es garantizado leer x = 10. Esto se debe a la escritura a y crea un punto de sincronización en el que todas las escrituras antes de dicho punto será visible después de la escritura.

Con la agrupación Fork Join, la combinación de ForkJoinTask creará un punto de sincronización. Ahora si t2.fork() y t1.invoke() la unión de t2 asegurará que se verán todas las escrituras que ocurrieron previamente. Como todas las escrituras anteriores están dentro de la misma estructura, será seguro para la visibilidad.

Estaré encantado de seguir explicando si eso no está tan claro.

+0

¿'invokeAll' es llamado por' coInvoke'? –

+0

Y, para complementar la respuesta, consulte también http://java.sun.com/docs/books/jls/third_edition/html/memory.html#64058. –

+0

@Danciel C. Sobral, pregunta interesante, cuando estaba escribiendo este ejemplo, en realidad estaba buscando el método coInvoke. Parece que el método coInvoke en sí mismo se ha purgado del código fuente. Eso es al menos no puedo encontrarlo por más tiempo. –

1

Solo supongo: fusionar incluye unir en un subproceso, y la unión garantiza la visibilidad.

La segunda parte es segura; No sé cómo se implementa la fusión.

Cuestiones relacionadas