ventajas son que porque por objetos objeto mutables modificar los inmutables inmutable clases java multithreading immutability

java - son - Publicación segura y la ventaja de ser inmutable versus efectivamente inmutable



porque los string son inmutables (4)

Entonces, ¿por qué es tan importante la inmutabilidad (vs. inmutabilidad efectiva)?

Creo que el punto principal es que los objetos verdaderamente inmutables son más difíciles de romper más adelante. Si has declarado un campo final , entonces es final, punto. Tendría que eliminar la final para cambiar ese campo, y eso debería hacer sonar una alarma. Pero si inicialmente dejaste fuera el final , alguien podría simplemente agregar un código que cambia el campo y boom, estás jodido, con solo un código agregado (posiblemente en una subclase), sin modificación del código existente.

También asumo que la inmutabilidad explícita permite al compilador (JIT) realizar algunas optimizaciones que de otra manera serían difíciles o imposibles de justificar. Por ejemplo, cuando se usan campos volatile , el tiempo de ejecución debe garantizar una relación de suceso antes con la escritura y lectura de hilos. En la práctica, esto puede requerir barreras de memoria, deshabilitar las optimizaciones de ejecución fuera de orden, etc., es decir, un impacto en el rendimiento. Pero si el objeto es (profundamente) inmutable (contiene solo referencias final a otros objetos inmutables), el requisito se puede relajar sin romper nada: la relación antes del suceso debe garantizarse solo con la escritura y la lectura de la única referencia , no el gráfico de objeto entero.

Por lo tanto, la inmutabilidad explícita hace que el programa sea más simple para que sea más fácil para los humanos razonar y mantener, y más fácil para que la computadora se ejecute de manera óptima. Estos beneficios crecen exponencialmente a medida que crece el gráfico de objetos, es decir, los objetos contienen objetos que contienen objetos: todo es simple si todo es inmutable. Cuando se necesita la mutabilidad, ubicarlo en lugares estrictamente definidos y mantener todo lo demás inmutable aún brinda muchos de estos beneficios.

Estoy releyendo Java Concurrency In Practice, y no estoy seguro de entender completamente el capítulo sobre la inmutabilidad y la publicación segura.

Lo que dice el libro es:

Los objetos inmutables pueden ser utilizados de forma segura por cualquier hilo sin sincronización adicional, incluso cuando la sincronización no se utiliza para publicarlos.

Lo que no entiendo es, ¿por qué alguien ( interesado en corregir su código ) publicará alguna referencia de forma insegura?

Si el objeto es inmutable y se publica de forma insegura, entiendo que cualquier otro subproceso que obtenga una referencia al objeto vería su estado correcto, debido a las garantías ofrecidas por la inmutabilidad adecuada (con campos final , etc.).

Pero si la publicación no es segura, es posible que otro hilo aún vea null o la referencia anterior después de la publicación, en lugar de la referencia al objeto inmutable, lo que me parece algo que a nadie le gustaría.

Y si se usa una publicación segura para asegurarse de que todos los subprocesos vean la nueva referencia, entonces incluso si el objeto es realmente inmutable (no hay campos final , pero no hay manera de silenciarlos), todo está seguro nuevamente. Como dice el libro:

Los objetos inmutables publicados de forma segura y segura pueden ser utilizados de forma segura por cualquier hilo sin sincronización adicional.

Entonces, ¿por qué es tan importante la inmutabilidad (vs. inmutabilidad efectiva)? ¿En qué caso se desearía una publicación insegura?


Es deseable diseñar objetos que no necesiten sincronización por dos razones:

  1. Los usuarios de tus objetos pueden olvidarse de sincronizar.
  2. A pesar de que la sobrecarga es muy pequeña, la sincronización no es gratuita, especialmente si sus objetos no se utilizan a menudo y por muchos hilos diferentes.

Debido a que las razones anteriores son muy importantes, es mejor aprender las reglas a veces difíciles y, como escritor, crear objetos seguros que no requieran sincronización en lugar de esperar que todos los usuarios de su código recuerden usarlo correctamente.

Además, recuerde que el autor no está diciendo que el objeto se publique de forma insegura, se publica de forma segura sin sincronización.

En cuanto a su segunda pregunta, acabo de marcar y el libro no le promete que otro hilo siempre verá la referencia al objeto actualizado, solo que si lo hace, verá un objeto completo. Pero puedo imaginar que si se publica a través del constructor de otro objeto (¿ Runnable ?), Será dulce. Eso sí ayuda con explicar todos los casos sin embargo.

EDITAR:

efectivamente inmutable e inmutable La diferencia entre efectivamente inmutable e inmutable es que en el primer caso todavía necesita publicar los objetos de una manera segura. Para los objetos verdaderamente inmutables esto no es necesario. Por lo tanto, se prefieren los objetos realmente inmutables porque son más fáciles de publicar por las razones que mencioné anteriormente.


La "publicación no segura" es a menudo apropiada en casos en los que tener otros subprocesos que ven el último valor escrito en un campo sería deseable, pero tener subprocesos que vean un valor anterior sería relativamente inofensivo. Un buen ejemplo es el valor hash en caché para String . La primera vez que se llama a hashCode() en un String , calculará un valor y lo almacenará en caché. Si otro hilo que llama a hashCode() en la misma cadena puede ver el valor calculado por el primer hilo, no tendrá que volver a calcular el valor del hash (ahorrando tiempo), pero no ocurrirá nada malo si el segundo hilo no lo hace. ver el valor hash. Simplemente terminará realizando un cálculo redundante pero inofensivo que podría haberse evitado. Habría sido posible tener hashCode() publicando el valor de hash de forma segura, pero los cómputos de hash redundantes ocasionales son mucho más económicos que la sincronización requerida para una publicación segura. De hecho, excepto en cadenas bastante largas, los costos de sincronización probablemente anularían cualquier beneficio del almacenamiento en caché.

Desafortunadamente, no creo que los creadores de Java imaginaran situaciones en las que el código escribiría en un campo y preferiría que fuera visible para otros subprocesos, pero no importaría demasiado si no lo está, y dónde se encuentra la referencia almacenada en el campo. A su vez, identificaría otro objeto con un campo similar. Esto conduce a situaciones en las que escribir código semánticamente correcto es mucho más engorroso y probablemente más lento que el código que podría funcionar, pero cuya semántica no estaría garantizada. No conozco ningún remedio realmente bueno para eso en algunos casos, aparte de usar algunos campos final gratuitos para garantizar que las cosas se "publiquen" correctamente.


Tenía la misma pregunta que el póster original al terminar de leer los capítulos 1-3. Creo que los autores podrían haber hecho un mejor trabajo elaborando esto un poco más.

Creo que la diferencia radica en que se puede observar que el estado interno de los objetos efectivamente inmutables se encuentra en un estado inconsistente cuando no se publican de forma segura, mientras que el estado interno de los objetos inmutables nunca se puede observar en un estado inconsistente.

Sin embargo, creo que se puede observar que la referencia a un objeto inmutable está desactualizada / obsoleta si la referencia no se publica de forma segura.