2012-06-25 14 views
10

Estoy buscando una forma eficiente de implementar una estructura de árbol simultánea. Si eso ayuda, suponga que tengo muchos más accesos de lectura que cambios en la estructura.Árbol concurrente eficiente

El árbol debe apoyar estas operaciones:

  • Adición y eliminación de nodos
  • Ordenar ramas cada vez que se inserta un nuevo nodo
  • iterar sobre todos los nodos (sin ConcurrentModificationException)
  • Busque un elemento por ruta

Respuesta

6

Tome un vistazo a: Concurrent-Trees el código de Google una manera de modificar las estructuras en forma de árbol sin bloquear.

El proyecto proporciona árboles Concurrent Radix y Suffix para Java. Admite lecturas y escrituras concurrentes, y las lecturas están libres de bloqueos. Funciona aplicando parches al árbol de forma atómica. Si bien estos tipos de árbol pueden no ser exactamente lo que usted desea, el enfoque que usa "parcheado" como se describe en TreeDesign es útil para cualquier tipo de estructura arborescente.

Los árboles están diseñados para casos de uso de lectura de concurrencia alta, donde (por ejemplo) un hilo de fondo podría estar insertando o eliminando entradas del árbol mientras que muchos hilos de primer plano continuarían atravesándolo sin impedimentos por las modificaciones.

+0

Esto es interesante pero inútil en mi caso de uso. Mis árboles son árboles reales (estructuras padre-hijo), no mapas de valores clave. –

+1

Evitaría usar palabras como "inútil". Esta respuesta fue contribuida para ayudarlo voluntariamente. Si está buscando árboles concurrentes de lectura en su mayoría, los algoritmos de bloqueo pueden ser una buena forma de hacerlo. Es posible que un árbol Radix no sea exactamente lo que estás buscando, pero como mencioné, el enfoque de aplicación de parches atómicos al que me he vinculado se puede aplicar a cualquier tipo de árbol para lecturas sin bloqueos, incluso si estás planeando escribir tu propio diseño personalizado árbol. Incidentalmente, los árboles radix son obviamente árboles, que tienen estructuras padre-hijo. – npgall

+0

+1 Mejoré la redacción para que tu intención sea más clara. –

3

Puede usar un bloqueo de lector-escritor en su estructura, i n una forma en que varios hilos pueden leer de forma simultánea pero solo un hilo a la vez puede modificarlo. Si algún hilo intenta modificar la estructura, no puede hacerlo hasta que todos los lectores hayan hecho sus lecturas. Si un hilo quiere leer, solo puede hacerlo si un escritor no está trabajando o está en proceso de hacer algunas modificaciones. Tal vez un vistazo a esto podría ayudar:

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

+0

+1 Para bloqueo de lectura/escritura – mishadoff

1

Idea básica con Bloqueo Lectura/Escritura

Para todas Escribir métodos usan siguiente lenguaje:

someWriteMethod(){ 
    writeLock.lock(); 
    // logic 
    writeLock.unlock(); 
} 

Para todos los métodos de lectura de uso similar código:

someReadMethod(){ 
    readLock.lock(); 
    // logic 
    readLock.unlock(); 
} 
  • Si al menos un método realiza la escritura, nadie puede obtener el bloqueo de lectura o escritura.
  • Si al menos un método realiza la lectura, cualquier número de hilo puede obtener un readlock.
  • Si al menos un método realiza la lectura, nadie puede obtener el bloqueo de escritura.

Nota, si su código (reemplazar el comentario lógico anterior) puede arrojar una excepción, asegúrese de liberar bloqueos antes de salir del método en la sección final.

+0

El bloqueo de lectura y escritura tiene una desventaja: no puede "actualizar" un bloqueo de lectura a escritura, por lo que debe saber con antelación si su operación modificará el árbol. Entonces eso necesitaría dos iteradores donde uno podría bloquear demasiado. –

+0

Supongo que al usar árboles, sabes de antemano qué operaciones modifican tu árbol, ¿no? – mishadoff

+0

Cuando le pido al árbol un iterador, el método que crea el iterador no puede saber si llamaré a remove() o no. –

5

La estructura de Java que está más cerca de lo que puede necesitar es ConcurrentSkipListSet (o tal vez ConcurrentSkipListMap).


Si necesita un enfoque más personalizado, puede implementar una estructura de árbol personalizada si tiene un bloqueo de lectura y escritura jerárquico. Aquí es un answerto una pregunta similar acerca de cómo implementar un entrante de bloqueo de lectura-escritura: https://stackoverflow.com/a/6154873/272388

+1

El CSLM no está realmente cerca. Es un * mapa ordenado * que tiene poco que ver con la estructura de un árbol. Por lo tanto, solo comparte una propiedad común con el 'TreeMap', ya que es un mapa ordenado, que no es relevante aquí. –

+0

Es por eso que hay una segunda parte de la respuesta ya que no conozco ninguna estructura de árbol incluida en Java que admita todas estas operaciones. Además, CSLM podría ser suficiente para algunos casos similares. – Kru

+1

Kru sigue siendo correcto: es la única estructura de datos en el tiempo de ejecución oficial que está más cerca de mi problema. Podría construir el árbol utilizando bloqueos ConcurrentSkipListMaps + anidados. –