Digamos que tenemos una clase Java muy simple MyClass
.Clase segura para subprocesos en Java mediante bloques sincronizados
public class MyClass {
private int number;
public MyClass(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Hay tres maneras de construir la clase de Java flujos seguros que tiene un cierto estado:
hacerla verdaderamente inmutable
public class MyClass { private final int number; public MyClass(int number) { this.number = number; } public int getNumber() { return number; } }
campo Definir
number
volatile
.public class MyClass { private volatile int number; public MyClass(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
utilizar un bloque
synchronized
. La versión clásica de este enfoque se describe en el Capítulo 4.3.5 de la concurrencia de Java en la práctica. Y lo curioso es que tiene un error en el ejemplo que se menciona en una errata para este libro.public class MyClass { private int number; public MyClass(int number) { setNumber(number); } public synchronized int getNumber() { return number; } public synchronized void setNumber(int number) { this.number = number; } }
Hay un hecho más que debe añadirse al contexto de la discusión. En un entorno multiproveedor, JVM puede reordenar las instrucciones fuera del bloque synchronized
conservando una secuencia lógica y ocurre antes de las relaciones especificadas por JVM. Puede causar la publicación de objetos que no están construidos correctamente para otro hilo.
Tengo un par de preguntas sobre el tercer caso.
¿Será equivalente a una siguiente fragmento de código:
public class MyClass { private int number; public MyClass(int number) { synchronized (this){ this.number = number; } } public synchronized int getNumber() { return number; } public synchronized void setNumber(int number) { this.number = number; } }
se impedirá que un reordenamiento en el tercer caso o posible que los JVM para reordenar intstructions y, por tanto, publicar objeto con valor por defecto en el campo
number
?Si la respuesta a la segunda pregunta es sí, tengo una pregunta más.
public class MyClass { private int number; public MyClass(int number) { synchronized (new Object()){ this.number = number; } } public synchronized int getNumber() { return number; } public synchronized void setNumber(int number) { this.number = number; } }
Este aspecto extraño synchronized (new Object())
se supone que previene el efecto de reordenamiento. ¿Funcionará?
Para que quede claro, todos estos ejemplos no tienen ninguna aplicación práctica. Solo tengo curiosidad sobre los matices del multihilo.
Hace algo (Fuerza todo en el bloque para completar antes de cualquier cosa que ocurra después en el hilo de construcción, por lo que si el hilo de construcción pasa inmediatamente la referencia a otro hilo después de que el constructor retorne, no necesita preocuparse por los campos que no son finales.) Simplemente no hace * suficiente * para cubrir * todos * los riesgos de concurrencia. – Affe
@Affe Dentro de un hilo, ya está garantizado que verá las cosas en el orden en que el código las dice, sin necesidad de sincronización. Pero no se requiere otro hilo para ver esos efectos en el mismo orden, debido a las carreras de datos. En otras palabras, si el hilo A hace 'A, B, C' (donde, por ejemplo,' A' es la sincronización, 'B' es la asignación de campo,' C' establece la referencia después de 'new'), hilo B se permite ver 'CAB' si no ocurre nada, antes del borde, que' synchronized (new Object()) 'nunca proporcionará. Por ejemplo, si el hilo B está en un núcleo diferente, 'C 'podría enjuagarse antes de' A'. – yshavit
sincronizando dentro del primer subproceso alrededor de la asignación B lo fuerza a ser visible antes de establecer la referencia C. Los efectos secundarios de consistencia de memoria del bloque sincronizado no están acoplados a los efectos secundarios de exclusión. Todavía se aplican para las operaciones realizadas en el primer hilo, ya sea que el otro hilo compita o no para el monitor de objetos. – Affe