react - objetos mutables e inmutables java
Los objetos inmutables son seguros para los hilos, pero ¿por qué? (7)
Los objetos inmutables son seguros para los hilos, pero ¿por qué?
Un objeto inmutable es un objeto que ya no se modifica una vez que se ha construido. Si además, el objeto inmutable solo se hace accesible a otros subprocesos después de que se haya construido, y esto se hace usando la sincronización adecuada, todos los subprocesos verán el mismo estado válido del objeto.
Si un hilo crea la variable de referencia de la clase inmutable creando su objeto y la segunda vez, el otro hilo comienza antes de que el primer subproceso finalice y cree otro objeto de la clase inmutable, ¿no será el hilo el uso de la clase inmutable? ¿inseguro?
No. ¿Qué te hace pensar eso? La seguridad de los subprocesos de un objeto no se ve afectada por lo que haces con otros objetos de la misma clase.
¿Están tratando de decir que el otro hilo puede volver a apuntar la variable de referencia a algún otro objeto de la clase inmutable y de esa manera los hilos estarán apuntando a diferentes objetos que dejan el estado inconsistente?
Intentan decir que cada vez que pasas algo de un hilo a otro, incluso si es solo una referencia a un objeto inmutable, necesitas sincronizar los hilos. (Por ejemplo, si pasa la referencia de un subproceso a otro almacenándolo en un objeto o un campo estático, varios subprocesos acceden a ese objeto o campo y deben ser seguros para subprocesos)
Si un hilo crea la variable de referencia de la clase inmutable creando su objeto y la segunda vez, el otro hilo comienza antes de que el primer subproceso finalice y cree otro objeto de la clase inmutable, ¿no será el hilo el uso de clase inmutable? ¿inseguro? La creación de un objeto inmutable también dice que todos los campos se marcarán como finales como ..... "puede ser necesario para garantizar un comportamiento correcto si se pasa una referencia a una instancia recién creada de un hilo a otro sin sincronización" ¿Están intentando diga que el otro hilo puede volver a apuntar la variable de referencia a algún otro objeto de la clase inmutable y de esa manera los hilos estarán apuntando a diferentes objetos dejando el estado inconsistente?
Además de otras respuestas publicadas, los objetos inmutables una vez creados, no pueden modificarse más. Por lo tanto, son esencialmente de sólo lectura.
Y como todos sabemos, las cosas de solo lectura siempre son seguras para subprocesos. Incluso en las bases de datos, las consultas múltiples pueden leer las mismas filas simultáneamente, pero si desea modificar algo, necesita un bloqueo exclusivo para eso.
Dos subprocesos no crearán el mismo objeto, así que no hay problema allí.
Con respecto a ''puede ser necesario asegurar ...'', lo que dicen es que si NO finaliza todos los campos, tendrá que asegurarse de tener el comportamiento correcto.
La inmutabilidad no garantiza la seguridad de los subprocesos, si los subprocesos solo acceden a los objetos inmutables para leer, no tiene que tomar precauciones adicionales para asegurarse de que los datos sean coherentes, pero si los subprocesos pueden manipular los datos, debe usar una forma segura para compartir datos entre hilos para que cada hilo vea datos consistentes.
La inmutabilidad no implica la seguridad del hilo. En el sentido, la referencia a un objeto inmutable se puede alterar, incluso después de que se haya creado.
//No setters provided
class ImmutableValue
{
private final int value = 0;
public ImmutableValue(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
public class ImmutableValueUser{
private ImmutableValue currentValue = null;//currentValue reference can be changed even after the referred underlying ImmutableValue object has been constructed.
public ImmutableValue getValue(){
return currentValue;
}
public void setValue(ImmutableValue newValue){
this.currentValue = newValue;
}
}
La seguridad del hilo es la seguridad del intercambio de datos, y porque en su código usted toma decisiones basadas en los datos que contienen sus objetos, la integridad y el comportamiento determinista del mismo es vital. es decir
Imagina que tenemos una variable de instancia booleana compartida en dos subprocesos que están a punto de ejecutar un método con la siguiente lógica
- Si el indicador es falso, imprimo "falso" y luego configuro el indicador en verdadero.
- Si el indicador es verdadero, imprimo "verdadero" y luego establezco el indicador en falso.
Si ejecuta continuamente en un solo bucle de subproceso, tendrá una salida determinista que se verá así:
falso - verdadero - falso - verdadero - falso - verdadero - falso ...
Pero, si ejecutó el mismo código con dos subprocesos, entonces, la salida de su salida ya no es determinista, la razón es que el subproceso A puede despertarse, leer la bandera, ver que es falso, pero antes de que pueda hacer algo. , el hilo B se despierta y lee la bandera, que también es falsa !! Entonces, ambos imprimirán en falso ... Y este es solo un escenario problemático que se me ocurre ... Como pueden ver, esto es malo.
Si elimina las actualizaciones de la ecuación, el problema desaparece, simplemente porque está eliminando todos los riesgos asociados con la sincronización de datos. por eso decimos que los objetos inmutables son seguros para los hilos.
Sin embargo, es importante tener en cuenta que los objetos inmutables no siempre son la solución, puede tener un caso de datos que necesita compartir entre diferentes subprocesos, en este caso hay muchas técnicas que van más allá de la sincronización simple y que pueden hacer una Hay mucha diferencia en el rendimiento de su aplicación, pero este es un tema completamente diferente.
Los objetos inmutables son importantes para garantizar que las áreas de la aplicación que estamos seguros de que no necesitan actualizarse, no se actualicen, por lo que estamos seguros de que no vamos a tener problemas de subprocesamiento múltiple.
Probablemente te interese echar un vistazo a un par de libros:
Este es el más popular: http://www.amazon.co.uk/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1329352696&sr=8-1
Pero personalmente prefiero este: http://www.amazon.co.uk/Concurrency-State-Models-Java-Programs/dp/0470093552/ref=sr_1_3?ie=UTF8&qid=1329352696&sr=8-3
¡Tenga en cuenta que el multihilo es probablemente el aspecto más complicado de cualquier aplicación!
En realidad, los objetos inmutables siempre son seguros para subprocesos, pero sus referencias pueden no serlo.
¿¿Confuso?? No deberías ser: -
Volviendo a lo básico : seguro para subprocesos simplemente significa que dos o más subprocesos deben trabajar en coordinación en el recurso u objeto compartido. No deben anular los cambios realizados por cualquier otro hilo.
Ahora String es una clase inmutable, siempre que un hilo intenta cambiarlo, simplemente termina creando un nuevo objeto. Entonces, simplemente el mismo hilo no puede hacer ningún cambio en el objeto original y hablar sobre el otro hilo sería como ir a Sun, pero el problema aquí es que generalmente usamos la misma referencia antigua para señalar el objeto recién creado.
Cuando hacemos código, evaluamos cualquier cambio en el objeto con la referencia solamente.
Declaración 1: cadena de caracteres = "123"; // inicialmente cadena compartida a dos hilos
Declaración 2: str = str + "FirstThread"; // para ser ejecutado por el hilo uno
Declaración 3: str = str + "SecondThread"; // para ser ejecutado por el hilo dos
Ahora, ya que no hay palabras clave sincronizadas, volátiles o finales para decirle al compilador que omita el uso de su inteligencia para la optimización (cualquier reordenamiento o almacenamiento en caché), este código se puede ejecutar de la siguiente manera.
- Load Statement2, así que str = "123" + "FirstThread"
- Load Statement3, por lo que str = "123" + "SecondThread"
- Store Statement3, así que str = "123SecondThread"
- Store Statement2, así que str = "123FirstThread"
y finalmente el valor en la referencia str = "123FirstThread" y durante algún tiempo si asumimos que afortunadamente nuestro hilo GC está durmiendo, que nuestros objetos inmutables aún no se han tocado en nuestro conjunto de cadenas.
Por lo tanto, los objetos inmutables siempre son seguros para subprocesos, pero sus referencias pueden no serlo. Para que sus referencias sean seguras para subprocesos, es posible que debamos acceder a ellas desde bloques / métodos sincronizados.