2010-05-19 25 views
7

por lo que quiero tener una lista de arrays que almacena una serie de cotizaciones de bolsa. pero hago un seguimiento del precio de la oferta, pregunto el precio y el último precio para cada uno.sincroniza lecturas a una colección java

por supuesto, en cualquier momento, la oferta o el último de un stock dado puede cambiar.

Tengo un hilo que actualiza los precios y uno que los lee.

quiero asegurarme de que al leer ningún otro hilo esté actualizando un precio. así que miré la colección sincronizada. pero eso parece prevenir solo la lectura mientras que otro hilo está agregando o eliminando una entrada a la lista de arrays.

Así que ahora estoy en el enfoque envoltorio:

public class Qte_List { 
private final ArrayList<Qte> the_list; 

public void UpdateBid(String p_sym, double p_bid){ 
    synchronized (the_list){ 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     q.bid=p_bid;} 
} 

public double ReadBid(String p_sym){ 
    synchronized (the_list){ 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     return q.bid;} 
} 

Así que lo que quiero lograr con esto es sólo un hilo puede estar haciendo nada - la lectura o la actualización de los contenidos de un la_lista - al mismo tiempo. ¿Me acerco a esto, verdad?

gracias.

+0

¿Está tratando de evitar que una escritura en un objeto Citar ocurra al mismo tiempo que una lectura? Si es así, bloquear la colección no logrará esto. Ver mi respuesta – DJClayworth

Respuesta

0

lo que tengo entendido que está utilizando el mapa para almacenar las cotizaciones; el número de citas nunca cambia, pero cada cita se puede leer o modificar para reflejar los precios actuales. Es importante saber que el bloqueo de la colección solo protege contra los cambios a los que se encuentran los objetos Citar en el mapa: no se restringe de ninguna manera la modificación de los contenidos de dichos Presupuestos. Si desea restringir ese acceso, deberá proporcionar el bloqueo en el objeto Citar.

En cuanto a su código sin embargo, no cree que tiene un problema de sincronización significativa. Si intenta hacer una lectura al mismo tiempo que una escritura, obtendrá el precio antes o el precio después de la escritura. Si no sabía que la escritura iba a ocurrir, eso no debería importarle. Es posible que necesite de bloqueo en un nivel superior de manera que

if (getBidPrice(mystock)<10.0) { 
    sell(10000); 
} 

sucede como una operación atómica y que no terminan vendiendo a 5,0 en lugar de 10,0.

Si el número de cotizaciones realmente no cambia, entonces te recomiendo que permite objetos QTE que se añadan sólo en el constructor de Qte_List. Esto haría que bloquear la colección sea irrelevante. El término técnico para esto es hacer Qte_List inmutable.

+0

gracias me haces pensar que necesito aclarar con más precisión qué bloquear. fideos en ella unas pocas horas. – jeff

+0

DJ - también, creo que ahora estoy confundido al intentar pensar en esto. Estoy mirando lo que escribiste en negrita arriba ... ¿cuál es la diferencia entre bloquear una colección y marcarla como definitiva? pensé que marcarlo como definitivo era lo que impedía los cambios en los objetos que están en el mapa. – jeff

+0

@Jeff final solo declara la variable como "inmutable", no el objeto en la variable. Entonces, la lista aún se puede modificar. Si desea que la Lista sea inmutable, consulte 'Collections.unmodifiableList()' – Hardcoded

1

Si esto va a funcionar, de todos modos no es necesario hacerlo usted mismo, puesto que ya se implementa en el marco de las colecciones

Collections.synchronizedList

+1

Una lista sincronizada no funcionará, ya que actualiza los atributos de las entradas en la lista en ese bloque sincronizado – Hardcoded

1

que parece un enfoque razonable. Puntillosa, sin embargo, es probable que no debe incluir la declaración de retorno dentro del bloque sincronizado:

public double ReadBid(String p_sym){ 
    double bid; 
    synchronized (the_list) { 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     bid = q.bid; 
    } 

    return bid; 
} 

No estoy seguro de si es sólo mi gusto o hay alguna Gotcha concurrencia involucrados, pero por lo menos me parece más limpio ;-).

2

Sí, está en el camino correcto y debería funcionar.

¿Pero por qué no utilizar la colección existente Hashtable, que está sincronizada, y proporciona una búsqueda clave-valor ya?

+2

La tabla Hash (y Vector) son anteriores a JDK 1.2 y deben evitarse. En su lugar, considere Collections.synchronizedMap (Map m) para crear un HashMap seguro para subprocesos. Además, aunque el OP no lo ha declarado explícitamente, sospecho que las cotizaciones deben ordenarse según un libro de pedidos típico. – Adamski

1

Su enfoque debería ser el truco, pero como dijo, solo puede haber un lector y un escritor a la vez. Esto no es muy escalable.

Existen algunas formas de mejorar el rendimiento aquí sin perder la seguridad de las hebras.
Se puede usar un ReadWriteLock por ejemplo. Esto permitirá múltiples lectores a la vez, pero cuando alguien obtiene el bloqueo de escritura, todos los demás deben esperar a que termine.

Otra forma sería utilizar una colección adecuada. Parece que podrías intercambiar tu lista con una implementación segura para subprocesos de Map. Eche un vistazo a ConcurrentMap documentation para posibles candidatos.

Editar:
Suponiendo que usted necesita pedir para su mapa, echar un vistazo a la interfaz de ConcurrentNavigableMap.

1

Lo que tiene funcionará, pero bloquear la lista completa cada vez que quiera leer o actualizar el valor de un elemento no es escalable. Si esto no importa, entonces estás bien con lo que tienes. Si desea que sea más escalable, considere lo siguiente ...

No indicó si necesita hacer cambios estructurales en la lista (agregando o quitando elementos), pero si no lo hace, una gran mejora sería mover la llamada a FindBySym() fuera de el bloque sincronizado. Entonces, en lugar de sincronizar en la lista, puede simplemente sincronizar en q (el objeto Qte). De esta forma puede actualizar diferentes objetos Qte al mismo tiempo. Además, si también puedes hacer que los objetos Qte sean inmutables, no necesitas ninguna sincronización. (para actualizar, simplemente use the_list [i] = new Qte (...)).

Si usted tiene que ser capaz de hacer cambios estructurales en la lista, se puede utilizar un ReentrantReadWriteLock para permitir lecturas y escrituras concurrentes exclusivos.

También tengo curiosidad por qué desea utilizar un ArrayList en lugar de un HashMap sincronizada.

+0

parece un hashmap tiene mucho más sentido. Probablemente prefiera enumerar demasiado sin pensar. Lo inmutable en un solo objeto Qte podría ayudar en parte del problema. pero necesito trabajar un poco más para entenderlo. cuál es la sintaxis que hace que los objetos Qte sean inmutables, o buscaré. también, ¿significa inmutable que para "cambiar" el objeto necesito reasignarlo? (Estoy viendo el texto en la respuesta que dice: "para actualizar, solo use la_lista [i] = nueva Qte (...)" – jeff

+0

Inmutable significa "no se puede cambiar". Por ejemplo, las cadenas son inmutables, mientras que las StringBuffers son . mutable no se puede cambiar el valor de un objeto String (por ejemplo, no se puede decir que la cadena s = "a"; s.append ("b");. una clase QTE inmutable tendría precio de la oferta, pregunte el precio y el último precio como variables miembro finales y estos 3 valores se pasarán al constructor. Las variables miembro pueden ser públicas o puede tener un getter (pero ningún setter) para cada una. – Angus

+0

También, en relación con el comentario de DJClayworth que "usted tampoco obtener el precio antes o el precio después de la escritura ", esto solo es cierto si Qte.bid es un valor de 32 bits (o menos) o volátil.Para los valores no volátiles de 64 bits, es posible leer en medio de una escritura y obtener datos incorrectos (consulte la especificación del lenguaje Java, sección 17.7 para obtener detalles), por lo que debe cambiar Qte.bid para que sea un flotante o int o déjalo doble y declararlo volátil (si no lo es). Una vez hecho esto, puede leer y escribir con seguridad q.bid sin sincronización. (y puedes ignorar mi sugerencia de inmutabilidad) – Angus

Cuestiones relacionadas