suma sincronizacion resueltos programas multihilos hilos fuente entre ejemplos con comunicacion codigo java concurrency synchronization

resueltos - sincronizacion de hilos en java



¿Debo sincronizarme en el resultado de una llamada invokeAll? (2)

No necesita el segundo synchronized si tiene el primero allí. Como señala Zed, invokeAll() se bloqueará hasta que todas las tareas se hayan completado. Mientras tanto, la sincronización alrededor de add() asegurará que los cambios en la colección sean visibles para todos los hilos, incluida la cadena de llamada original.

En cuanto a si necesita el primero (que no preguntó), traté de eliminar ambos bloques synchronized y no pude conseguir que fallara, pero tenerlo allí probablemente sea la apuesta más segura. De acuerdo con javadoc para LinkedList :

Si varios subprocesos acceden a LinkedList al mismo tiempo, y al menos uno de los subprocesos modifica estructuralmente la lista, se debe sincronizar externamente.

Las otras implementaciones de la Collection "segunda generación" tienen advertencias similares.

Tenga en cuenta por cierto que no tiene nada de mágico sincronizar en la colección en sí. Podría declarar un mutex por separado (cualquier antiguo Object ) en la clase externa, o sincronizar en la instancia de clase externa, y eso funcionaría igual de bien, siempre y cuando todos los WorkHorse sincronicen en la misma cosa.

Estoy mejorando un algoritmo existente que consiste en múltiples pasos independientes para usar tareas concurrentes. Cada una de las tareas creará múltiples objetos para mantener sus resultados. Al final, me gustaría tener una lista de todos los resultados para regresar del método de control. Por el momento, mi código se ve algo así

private final ExecutorService pool = ...; // A single task to be performed concurrently with other tasks. private class WorkHorse implements Callable<Void> { private final Collection<X> collect; public WorkHorse(Collection<X> collect, ...) { this.collect = collect; } public Void call() { for (...) { // do work synchronized (this.collect) { this.collect.add(result); } } return null; } } // Uses multiple concurrent tasks to compute its result list. public Collection<X> getResults() { // this list is supposed to hold the results final Collection<X> collect = new LinkedList<X>(); final List<WorkHorse> tasks = Arrays.asList( new WorkHorse(collect, ...), new WorkHorse(collect, ...), ...); this.pool.invokeAll(tasks); // ## A ## synchronized (collect) { return collect; } }

¿De verdad necesito el synchronized en "## A ##" para imponer una relación de pasar antes con las operaciones de modificación en las tareas de los trabajadores? ¿O puedo confiar en que todas las operaciones de escritura ocurrieron después de invokeAll returns y ser visible para el hilo de control? ¿Y hay alguna razón para que no devuelva la colección de resultados desde su propio bloque synchronized ?


No, no necesitas eso. La documentación de invoke All indica que todos los trabajos deben realizarse cuando vuelva. Por lo tanto, no debe haber más acceso para recopilar cuando llegue a la declaración de devolución.