Documentos de Académico
Documentos de Profesional
Documentos de Cultura
3.1. Visibilidad La visibilidad es sutil porque las cosas que no pueden ser contadas como
intuitivas.InasingleͲthreadedenvironment, si usted escribe debido a una variable variable y luego
lee esa variable sin escribir nada, puede esperar que se le devuelva el mismo valor.Esto parece ser
algo natural.En general, no hay garantía de que el hilo que se está leyendo tendrá un valor escrito
por otro hilo a tiempo, o incluso en todos los casos. Dos hilos, el hilo principal y el hilo principal,
acceden a las variables compartidas listas y con un número, el hilo principal inicia el hilo principal y
el hilo superior a 42 y el hilo inferior a 42 y al final a la verdad.Si bien puede parecer obvio que No-
Visibilidad imprimirá42, de hecho es posible que imprima cero, o que nunca termine todo! debido
a que no utiliza la sincronización adecuada, no hay garantía de que los valores deady y el número
escrito por el tema en cuestión sean visibles en el hilo superior.
Incluso de manera más extraña, NoVisibility podría imprimir, ya que la escritura de la lectura
podría hacerse visible a la de la lectura antes de escribir el número, un fenómeno conocido como
orden de pedido.No hay garantía de que las operaciones en un hilo de rosca se realicen en el
orden dado por el programa, siempre que no se detecte una orden desde el hilo de rosca
Ͳevenifthereorderingisapparenttootherthreads.[1] Cuando el hilo de rosca escribe el primer
número y se hace sin sincronización, el hilo del lector podría ver que esas escrituras suceden en el
orden opuesto Ͳ o en absoluto.
En ausencia de sincronización, el compilador, el procesador y el tiempo de ejecución pueden hacer
algunas cosas muy extrañas
orden en que las operaciones parecen ejecutarse. Los intentos de razonar sobre el orden en que
las acciones de memoria "deben" suceder en programas multiproceso insuficientemente
sincronizados seguramente serán incorrectos.
NoVisibility es tan simple como un programa concurrente puede obtener dos hilos y dos variables
compartidas, y aun así es demasiado fácil llegar a conclusiones erróneas sobre lo que hace o
incluso si terminará. Razonar sobre programas concurrentes insuficientemente sincronizados es
prohibitivamente difícil. Todo esto puede sonar un poco aterrador, y debería. Afortunadamente,
hay una manera fácil de evitar estos problemas complejos: utilice siempre la sincronización
adecuada siempre que los datos se compartan entre subprocesos.
NoVisibility demostró una de las formas en que los programas insuficientemente sincronizados
pueden causar resultados sorprendentes: datos obsoletos. Cuando el hilo del lector examina listo,
puede ver un valor desactualizado. A menos que se use la sincronización cada vez que se accede a
una variable, es posible ver un valor obsoleto para esa variable. Peor aún, la obsolescencia no es
todo o nada: un subproceso puede ver un valor actualizado de una variable, pero un valor
obsoleto de otra variable que se escribió primero.
Cuando la comida está rancia, por lo general todavía es comestible, solo que menos agradable.
Pero los datos obsoletos pueden ser más peligrosos. Si bien un contador de visitas fuera de fecha
en una aplicación web puede no ser tan malo, [2] los valores obsoletos pueden causar graves fallas
de seguridad o de vida. En NoVisibility, los valores obsoletos pueden hacer que imprima el valor
incorrecto o evitar que el programa finalice. Las cosas pueden complicarse aún más con valores
obsoletos de referencias de objetos, como los punteros de enlace en una implementación de lista
vinculada. Los datos obsoletos pueden causar fallas graves y confusas, como excepciones
inesperadas, estructuras de datos corruptas, cálculos inexactos y bucles infinitos.
Cuando un hilo lee una variable sin sincronización, puede ver un valor obsoleto, pero al menos ve
un valor que fue colocado allí por algún hilo en lugar de algún valor aleatorio. Esta garantía de
seguridad se denomina seguridad de aire fino.
La seguridad del aire exterior se aplica a todas las variables, con una excepción: las variables
numéricas de 64 bits (dobles y largas) que no se declaran volátiles (consulte la Sección 3.1.4). El
modelo de memoria Java requiere que las operaciones de recuperación y almacenamiento sean
atómicas, pero para las variables largas y dobles no volátiles, la JVM puede tratar una lectura o
escritura de 64Ͳbit como dos 32Ͳ separadas para recuperar los 32 bits altos de un valor y los 32
bits bajos de otro. [3] Por lo tanto, incluso si no le importan los valores obsoletos,
El bloqueo intrínseco se puede utilizar para garantizar que un hilo vea los efectos de otro de
manera predecible, como se ilustra en la Figura 3.1. Cuando el hilo A ejecuta un bloque
sincronizado, y posteriormente el hilo B entra en un bloque sincronizado protegido por el mismo
bloqueo, los valores de las variables que eran visibles para A antes de liberar el bloqueo
están garantizados para ser visibles para B al adquirir la cerradura. En otras palabras, todo lo que A
hizo en o antes de un bloque sincronizado es visible para B cuando ejecuta un bloque sincronizado
protegido por el mismo bloqueo. Sin sincronización, no existe tal garantía.
Ahora podemos dar la otra razón para que la regla requiera que todos los hilos se sincronicen en el
mismo bloqueo al acceder a una variable mutable compartida, para garantizar que los valores
escritos por un hilo sean visibles para otros hilos. De lo contrario, si un hilo lee una variable sin
mantener el bloqueo apropiado, podría ver un valor obsoleto.
El lenguaje Java también proporciona una forma alternativa, más débil de sincronización, variables
volátiles, para garantizar que las actualizaciones de una variable se propaguen de manera
predecible a otros subprocesos. Cuando un campo se declara volátil, se notifica al compilador y al
tiempo de ejecución que esta variable se comparte y que las operaciones en él no deben
reordenarse con otros
Una buena manera de pensar sobre las variables volátiles es imaginar que se comportan más o
menos como la clase SynchronizedInteger en el Listado 3.3, reemplazando las lecturas y escrituras
de la variable volátil con llamadas para obtener y establecer.
La variable no realiza ningún bloqueo y, por lo tanto, no puede hacer que el hilo en ejecución se
bloquee, lo que hace que las variables volátiles sean un mecanismo de sincronización de peso más
ligero que el sincronizado