EDIT: Supongo que se refería a Queue<Object> objectList
en lugar de ConcurrentLinkedQueue<Object> objectList
. ConcurrentLinkedQueue<Object>
ya hace toda su seguridad de hilo para usted, lo que significa que puede llamar al objectList.peek()
todo lo que quiera sin preocuparse por las condiciones de carrera. Esto es excelente si está desarrollando programas de subprocesos múltiples, pero no tan buenos para aprender sobre seguridad de subprocesos.
Sus métodos no necesitan ser synchronized
, suponiendo que tiene el funcionamiento de una rosca en una instancia del objeto a la vez, pero sin embargo, si es necesario tener varias instancias de la clase que todos se refieren a la misma variable de clase estática, tienen que synchronized
sobre la variable de clase, así:
public static void getHeadObject() {
synchronized(safe.objectList) {
System.out.println(objectList.peek().toString());
}
}
Esto bloquea el objectList
y no permite que se pueda leer o escribir en cualquier otro hilo tan pronto como el programa se encuentra dentro del bloque de sincronización. Haga lo mismo para todos los demás métodos que sean synchronized
.
NOTA:
Sin embargo, puesto que está haciendo sólo una operación de obtención sencilla List.peek()
, que realmente no es necesario sincronizar a través de la objectList
ya que en una condición de carrera, este obtendrá un valor de el List
u otro. El problema con las condiciones de carrera es cuando se realizan múltiples operaciones complejas de lectura/escritura, y el valor cambia entre ellas.
Por ejemplo, si usted tenía una clase PairInt
con PairInt.x
y PairInt.y
campos, con la restricción de que x = 2y
, y que quería hacer
System.out.println(myIntPair.x.toString() + ", " + myIntPair.y.toString());
y otro hilo fue la actualización del valor de x
y y
en al mismo tiempo,
myIntPair.y = y + 3;
myIntPair.x = 2 * y;
Y la escritura hilo modificado myIntPair
en medio de su hilo de lectura myIntPair.x.toString()
y myIntPair.y.toString()
puede obtener un resultado que se parece a (10, 8)
, lo que significa que si está operando bajo el supuesto de que x == 2 * y
podría bloquear su programa.
En ese caso, su lectura tiene que utilizar un synchronized
, pero para cosas más simples como peek()
en un simple object
que se añaden o se eliminan, sin modificar, mientras que en la cola, el synchronized
puede, en la mayoría de los casos ser dropeado De hecho, para string
, int
, bool
, y similares, se debe descartar la condición synchronized
para una lectura simple.
Sin embargo, las escrituras siempre deben ser synchronized
en operaciones que no son explícitamente seguras para subprocesos, es decir, que ya las maneja Java. Y en cuanto a adquirir más de un recurso, o requiere que el recurso de suspender el mismo durante toda la operación como lo hace varias líneas de lógica en ello, entonces DEBE UTILIZARsynchronized
Por qué es 'addObject' un método de instancia? ¿Por qué no estático? ¿Por qué estás sincronizando alrededor de un objeto concurrente de todos modos? Ellos ya son enhebrables. – Wug
¿Qué quiere decir con estado inconsistente? –
Estoy asumiendo que quería decir 'cola