Tengo una estructura de datos que consta de nodos vinculados. Puedes pensarlo como una simple LinkedList. Cada nodo de la lista consta de algún valor y un siguiente campo apunta al otro nodo o nulo si es el último nodo. El primer nodo funciona como raíz, no tiene ningún valor, solo apunta al siguiente nodo. Todos los otros nodos son prácticamente inmutables, una vez que se crean, ni su valor ni su próximo campo cambian durante la vida útil, a menos que la estructura esté siendo eliminada y se relacione con una situación específica.variables volátiles y barrera de memoria en java
Una (solo una) cadena agrega nuevos nodos al principio de la lista. Esto se logra construyendo un nuevo objeto, estableciendo sus campos y configurando el siguiente campo para el objeto apuntado por la raíz, luego estableciendo el próximo campo de la raíz para este nuevo nodo.
Los otros nodos exploran la estructura solo para realizar lecturas. Tienen una referencia al nodo raíz, luego pasan por los otros nodos hasta que encuentren lo que buscan o lleguen al final de la lista.
Mi pregunta es: ¿es suficiente hacer que el siguiente campo sea volátil? Desde mi comprensión del modelo de memoria Java, si el hilo principal (el que agrega nuevos nodos) realizará una escritura volátil al agregar un nuevo nodo, todo se sincronizará perfectamente y no se producirán incoherencias.
¿También es correcto suponer que en la arquitectura x86 las lecturas de una variable volátil no incurrirán en degradación del rendimiento? Como los otros hilos navegarán frecuentemente por la estructura leyendo el siguiente campo, es importante que esto se pueda hacer libremente sin barreras de memoria, etc.
También tengo una preocupación más. Los hilos que van a examinar la estructura también contendrán algunos nodos adicionales. Estos nodos serán completamente locales de subprocesos, es decir, solo los usará el subproceso que los creó y no se compartirán en absoluto. Para estos nodos adicionales, no es necesario que el siguiente campo sea volátil. Además, configurar el siguiente campo volátil emitirá una barrera de memoria que causará una pérdida de rendimiento indeseable. Me pregunto si hay alguna manera de evitar esto. Idealmente, sería perfecto si el próximo campo funcionara a veces como un campo volátil y, a veces como un campo normal;) o si tuviera un control total y pudiera emitir barreras de memoria por mi cuenta, siempre que lo necesite.
Editar:
También me preguntaba ¿Sería posible sincronizar alguna manera todas estas escrituras en una variable volátil diferente? Por ejemplo, ¿alguna otra variable estática completamente no relacionada? Dado que la escritura volátil vacía todas las escrituras pendientes, ¿no sería posible que el siguiente campo no sea volátil y en su lugar se escribiría una variable volátil diferente después de que el hilo de actualización haga todo el trabajo?
No parece muy seguro para mí, ya que no ocurre nada antes de la relación y las escrituras anteriores pueden volver a ordenarse. Las siguientes asignaciones de campo podrían reordenarse con las asignaciones de campos de valor que conducen a la iteración de subprocesos que observan el estado de objeto incoherente.
Pero tal vez es posible llegar a un esquema que sería seguro?¿Qué tal este:
hilo actualización primero construye un nuevo objeto, inicializa sus campos de valor, establece su campo siguiente al nodo apuntado por el nodo raíz, realiza una escritura volátil en alguna variable estática, establece el siguiente campo de el nodo raíz hasta el nodo de nueva creación
+1. Buena explicación de la semántica de la barrera de memoria de 'volátil', aunque debe señalarse que las JVM anteriores a JSR133 (es decir, Java <5.0) no tenían la misma semántica ... – thkala
Buen punto gracias por incluir como nota. –
Gracias por una gran respuesta. Espero que hayas entendido bien lo que está pasando en mi código. No hay una referencia raíz, solo un nodo raíz. Es por eso que establezco dos campos siguientes diferentes (uno del nuevo objeto y otro del nodo raíz). – ciamej