¿Cómo cambiar el orden de un elemento en una lista en Java y ser seguro para subprocesos?

Tengo una lista de elementos y cuando verifico un elemento, aparece al final de la lista. Quiero que la aplicación sea segura para subprocesos.

¿El código del subproceso "checkItem" es seguro con respecto a la lista de "elementos"?

  public class ItemListImpl implements ItemList {

        List<Item> items = Collections.synchronizedList(new ArrayList<Item>());

        /**
         * Checks an item and brings it at the end of the list
         */
        public void checkItem(int index) {
            Item item = items.get(index);
            item.check();

            synchronized (items) {
                items.remove(item);
                items.add(items.size(), item);
            }

        }
    }

(olvide el hecho de que uso el índice del elemento. Usaré el objeto o una identificación)

Respuesta 1

Necesitamos darnos cuenta de que itemses una lista sincronizada, y que una lista sincronizada se utiliza a sí misma como su mutex primitivo. Esto significa que todas las operaciones de listas individuales Y TAMBIÉN el synchronizedbloque se están sincronizando items.

Por lo tanto, el único punto en el que pueden ocurrir cosas de forma no sincronizada es en la brecha entre la getfinalización de la llamada y el inicio del synchronizedbloqueo. Entonces, ¿eso es un problema?

Bueno, consideremos lo que podría suceder:

  • Si algún otro hilo mueve la posición del Item, no importa. Encontraremos simplemente moverlo al final de todos modos.

  • Si algún otro hilo elimina el Item, no importa. Nuestro llamado a removevolverá false, pero aún así agregaremos el artículo nuevamente.

Los problemas solo surgen si es posible que un determinado Itemaparezca en más de un lugar en la itemslista. Si eso ocurre, entonces es posible que el código mueva el elemento de elementos en la posición incorrecta al final de la lista; p.ej

  1. El hilo A llama a get (42) a buscar el artículo I.
  2. El hilo B inserta el artículo I en la posición 1.
  3. El subproceso A completa la comprobación y elimina y vuelve a leer el elemento I ... pero como ahora también aparece en la posición 1, en realidad elimina y agrega esa copia, no la copia en la posición 42.

En resumen, el código es seguro para subprocesos si podemos suponer que un objeto Item dado puede aparecer como máximo una vez en la lista. Si no podemos suponer eso, existe el riesgo de mover el objeto a la posición incorrecta.

También debe tenerse en cuenta que el código no funcionará correctamente en el caso de que un elemento determinado pueda aparecer más de una vez. El problema es que remove(item)elimina la primera referencia a la iteminstancia que encuentra, no necesariamente la que está en la posición index. Hay dos maneras de ver esto. Si este comportamiento no es intencionado, es un error. Si se pretende, entonces la preocupación por la seguridad del hilo probablemente no sea un problema.


De cualquier manera, el código es seguro con respecto al modelo de memoria, suponiendo que el checkmétodo sea seguro para subprocesos.

Respuesta: 2

entonces tengo un código que debería multiplicar dos números binarios como String sin usar ParseInt. Mi código en realidad funciona con diferencia, pero se multiplica como números decimales. Algo en la parte donde ...

Eclipse 3.5.0 Estoy agregando un servidor JBoss 4.3.0, lo he configurado correctamente, pero cuando hago clic en él para ver su configuración, recibo el siguiente error: Se produjeron problemas al invocar el código de ...

¿Cómo leer líneas en un archivo usando Java sin perder las pestañas, espacios al principio (sangría)? Necesito esto para leer un código fuente y luego imprimirlo. Lo estoy haciendo así: br = ...

Estoy usando Spring MVC, y en la configuración estoy usando la siguiente línea para hacer que algunos archivos Javascript estén disponibles para mi aplicación: <mvc: resources mapping = "/ resources / **" location = "/, ...