util que copyonwritearraylist concurrent java arrays concurrency

que - java array seguridad de subprocesos



copyonwritearraylist que es (5)

Como read () no está sincronizado, podría tener el siguiente escenario:

Thread A enters write() method Thread A writes to nwriting = 0; Thread B reads from nwriting =0; Thread A increments nwriting. nwriting=1 Thread A exits write();

Ya que quiere garantizar que sus direcciones de variables nunca entren en conflicto, ¿qué hay de algo como (descontando los problemas del índice de matriz):

int i; synchronized int curr(){ return i; } synchronized int next(){ return ++i;} int read( ) { return values[curr()]; } void write(int x){ values[next()]=x; }

¿Hay algún problema de concurrencia con la lectura de un hilo de un índice de una matriz, mientras que otro hilo escribe en otro índice de la matriz, siempre que los índices sean diferentes?

por ejemplo (este ejemplo no necesariamente se recomienda para uso real, solo para ilustrar mi punto)

class Test1 { static final private int N = 4096; final private int[] x = new int[N]; final private AtomicInteger nwritten = new AtomicInteger(0); // invariant: // all values x[i] where 0 <= i < nwritten.get() are immutable // read() is not synchronized since we want it to be fast int read(int index) { if (index >= nwritten.get()) throw new IllegalArgumentException(); return x[index]; } // write() is synchronized to handle multiple writers // (using compare-and-set techniques to avoid blocking algorithms // is nontrivial) synchronized void write(int x_i) { int index = nwriting.get(); if (index >= N) throw SomeExceptionThatIndicatesArrayIsFull(); x[index] = x_i; // from this point forward, x[index] is fixed in stone nwriting.set(index+1); } }

edit: criticar este ejemplo no es mi pregunta, literalmente solo quiero saber si el acceso de matriz a un índice, al mismo tiempo que el acceso a otro índice, plantea problemas de concurrencia, no puedo pensar en un ejemplo simple.


El ejemplo tiene muchas cosas que difieren de la pregunta en prosa.

La respuesta a esa pregunta es que se accede a los distintos elementos de una matriz de manera independiente, por lo que no necesita sincronización si dos subprocesos cambian elementos diferentes.

Sin embargo, el modelo de memoria Java no ofrece ninguna garantía (que yo sepa) de que un valor escrito por un subproceso será visible a otro subproceso, a menos que sincronice el acceso.

Dependiendo de lo que realmente estés tratando de lograr, es probable que java.util.concurrent ya tenga una clase que lo haga por ti. Y si no es así, todavía recomiendo echar un vistazo al código fuente de ConcurrentHashMap , ya que su código parece estar haciendo lo mismo que hace para administrar la tabla hash.


No estoy realmente seguro de que la sincronización solo del método de write , mientras que deje el método de read sincronización, funcionaría. No son realmente todas las consecuencias, pero al menos podría llevar a que el método de read devuelva algunos valores que la write acaba de anular.


Sí, ya que el intercalado de caché incorrecto todavía puede ocurrir en un entorno multi-cpu / core. Hay varias opciones para evitarlo:

  • Utilice la biblioteca no segura de Sun-private para establecer un elemento atómicamente en una matriz (o la característica jsr166y agregada en Java7
  • Utilizar AtomicXYZ [] array
  • Use un objeto personalizado con un campo volátil y tenga una matriz de ese objeto.
  • Use el ParallelArray de jsr166y addendum en su algoritmo

Si bien no obtendrá un estado no válido al cambiar las matrices como lo menciona, tendrá el mismo problema que ocurre cuando dos subprocesos están viendo un entero no volátil sin sincronización (consulte la sección en el Tutorial de Java sobre errores de coherencia de la memoria ). Básicamente, el problema es que el subproceso 1 puede escribir un valor en el espacio i, pero no hay garantía cuando (o si) el subproceso 2 verá el cambio.

La clase java.util.concurrent.atomic.AtomicIntegerArray hace lo que usted quiere hacer.