2011-12-08 16 views
7

Como se sugiere en varias respuestas a esta pregunta:¿ReadWriteLock hace innecesaria la palabra clave sincronizada?

What is the name of this locking technique?

he implementado un ReentrantReadWriteLock y vi un gran aumento de velocidad (yo sabía que había algo de contención de bloqueo en uno de mi clase y utilizando un bloqueo de reentrada hizo cosas de velocidad ayuda arriba).

Pero ahora me pregunto: si dentro de una clase todos los accesos (tanto de lectura y escritura) se realizan mediante el bloqueo primero una operación de lectura-escritura de bloqueo o un bloqueo, ¿significa la palabra clave sincronizada no debe ser usado más en esa clase?

Por ejemplo, aquí es un funcionario de Java 1.6 ejemplo encontrar en http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

class RWDictionary { 
    private final Map<String, Data> m = new TreeMap<String, Data>(); 
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
    private final Lock r = rwl.readLock(); 
    private final Lock w = rwl.writeLock(); 

    public Data get(String key) { 
     r.lock(); 
     try { return m.get(key); } 
     finally { r.unlock(); } 
    } 
    public String[] allKeys() { 
     r.lock(); 
     try { return m.keySet().toArray(); } 
     finally { r.unlock(); } 
    } 
    public Data put(String key, Data value) { 
     w.lock(); 
     try { return m.put(key, value); } 
     finally { w.unlock(); } 
    } 
    public void clear() { 
     w.lock(); 
     try { m.clear(); } 
     finally { w.unlock(); } 
    } 
} 

No hay sincronizar palabra clave.

Ahora se dan cuenta de que uno de los puntos de este tipo de cerraduras es ser más rápido que otros métodos (en este caso más rápido que sincronizar), pero ¿cuál es la explicación técnica detrás de esto?

¿El uso de un bloqueo de lectura y escritura en una clase en cada método get/update "reemplaza" la palabra clave sincronizar para estos métodos?

+0

Supongo que estaba sincronizando en la instancia, como 'synchronize (this)'. En cambio, si se sincronizara en dos objetos diferentes, uno para lectura y otro para escritura, habría logrado el mismo rendimiento. Con 'this' sync, cuando' put' se está procesando, innecesariamente 'get' también se espera. Con diferentes objetos de bloqueo, esta contención desaparece. – srkavin

+0

Para la mayoría de las implementaciones de mapas, * es * necesario para hacer que get wait mientras put está en progreso. – Affe

+0

@srkavin La disputa se habría ido, pero también la visibilidad de la memoria garantiza. Su 'get' pudo haber visto una actualización parcial del' put', ya que no estaban sincronizados entre sí. – yshavit

Respuesta

10

si usted lee el javadocs en ReadWriteLock y de bloqueo, que específicamente decir que las cerraduras tienen para proporcionar la misma semántica de memoria como el synchronized palabra clave: implementaciones

de todos los seguros deben cumplir la misma semántica de sincronización de la memoria como proporcionada por la incorporada en el bloqueo del monitor, como se describe en The Java Language Specification, tercera edición (Modelo 17.4 memoria):

(. Eso es desde el javadoc de bloqueo, el ReadWriteLock refiere a Lock para describir su semántica)

Por lo tanto, sí, reemplaza la palabra clave synchronized. De hecho, puedes reemplazar cada bloque synchronized en tu código con un bloqueo y tener la misma semántica (y, dependiendo de jvm, posiblemente incluso un pequeño impulso en el rendimiento). Pero estarías cambiando un poco la velocidad por mucha más verborrea , y si alguna vez olvida desbloquear uno de esos bloqueos, podría bloquear su programa.

¿Qué poderes mucho de esto es algoritmos de no bloqueo (compare-and-swap ser el corazón de ellos) en combinación con la semántica de memoria de volatile campos, que especifican que si se escribe en un campo volatile, cualquier tema que posteriormente se lee que el campo tiene que ver al menos el mismo estado del mundo que viste cuando lo escribiste. (También podrían ver todo o parte de lo que sucedió después de esa escritura.) Esas herramientas pueden generar un código bastante rápido, pero también son sutiles y fáciles de equivocarse: casi siempre es mejor permanecer en el nivel superior. construcciones (como el ReadWriteLock que estás usando).

Cuestiones relacionadas