2011-02-06 20 views
16

Hasta donde yo sé, wait() y notify() han sido reemplazados por mejores mecanismos de simultaneidad. Entonces, ¿qué mejor alternativa elegirías, digamos para implementar a synchronized queue?¿Cuál es la mejor alternativa para esperar ... notificar la sincronización de bajo nivel?

¿En qué sentido exactamente son "mejores"?

Editar: Esto ("implementar una cola sincrónica") es una pregunta de la entrevista. Una respuesta aceptable no puede usar BlockingQueue u otra implementación de cola. Sin embargo, podría usar otras construcciones de sincronización como CountDownLatch. No tengo una lista exhaustiva de clases permitidas y prohibidas: usa tus cabezas.

+7

No implementaría una cola sincronizada. Utilizaría una de las muchas implementaciones de BlockingQueue: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html –

+1

@Mike - Me estoy preparando para entrevistas de trabajo . En la vida real, usaría algo existente en lugar de reinventar. – ripper234

+0

Entonces me temo que no entiendo la pregunta. Los bloques sincronizados y wait/notify han sido reemplazados por abstracciones de mayor nivel en la forma de las clases en el paquete java.util.concurrent, no por nuevas construcciones de lenguaje. Si la intención de la pregunta es hacer uso de algunas de las clases java.util.concurrent, ¿con cuáles excluimos la respuesta? –

Respuesta

17

synchronized/wait()/notify()/notifyAll() han sido reemplazados directamente por los métodos de clase Lock lock()/unlock()/newCondition() y Condition await()/signal()/signalAll().

Existen varios beneficios para estos, para empezar, permitir una semántica adicional como políticas de equidad, así como características como el bloqueo distribuido. El soporte para múltiples objetos Condition permite una señalización mucho más fina, así como la espera ininterrumpida y la espera hasta algún momento, etc.

Por ejemplo, el código vinculado tiene objetos separados que intenta usar para la señalización (que fallará debido a el hecho de que los monitores relevantes no se mantienen en espera). Esto es directamente reemplazable por el uso de un único bloqueo con múltiples condiciones.

En términos de mejoras, la funcionalidad adicional puede ser valiosa. En Java5, las implementaciones de bloqueo explícito en realidad se desempeñaron mejor que los monitores de JVM, pero básicamente eliminaron el código de Doug Lea para la JVM y el rendimiento ahora es más o menos equivalente.

3

Al leer la fuente de la implementación ArrayBlockingQueue, se revela el uso de Conditions como reemplazo de los métodos del supervisor de objetos "wait/notify/notifyAll". Además, se utiliza un ReentrantLock en lugar de la palabra clave "sincronizada" para lograr un comportamiento de exclusión mutua y una semántica similares. Parece que el paquete java.util.concurrent.locks es lo que estás buscando. Estas nuevas interfaces son mejores porque proporcionan una funcionalidad adicional que no es posible con las construcciones de sincronización y bloqueo originales, como múltiples conjuntos de espera y bloqueos selectivos de lectura o escritura (en lugar de leer siempre y escribir).

El paquete java.util.concurrent.atomic también proporciona interfaces a las instrucciones compare-and-swap que son útiles para non-blocking algorithms, que son potencialmente mucho más rápidas que sus alternativas de bloqueo pero tienen sus propios desafíos.

+0

Consulte mi pregunta editada: esta no es realmente una respuesta relevante. – ripper234

+0

Gotcha, aquí hay otra puñalada. – maerics

4

Ya existen muchas implementaciones en el paquete java.util.concurrent. P.ej. - ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue.

También wait() y notify() no se han reemplazado. Se han introducido nuevas utilidades que proporcionan funcionalidades adicionales y beneficios de rendimiento. Ver por ejemplo el paquete java.util.concurrent.locks.

Le recomendaría que lea this introducción. Proporciona una visión general alta que debe responder a su pregunta.

Saludos.

Edición 1: Ok, entonces, por ejemplo, se puede utilizar una implementación de java.util.concurrent.locks .Lock para implementar una operación de retirada de cola que los tiempos de espera y en el mismo tiempo equidad subvenciones a las roscas acceso a la cola. Tal implementación es ReentrantLock que tiene un constructor que acepta la política de equidad. El tiempo tryLock() favorece esta propiedad. También puede agregar algún soporte de depuración para contar los hilos de espera en la cola, etc. Esto sería mucho más difícil de implementar simplemente con wait() y notify() supongo.

En conclusión ReentrantLock es "mejor" que las contrapartes de bajo nivel en sus capacidades extendidas. El comportamiento básico es el mismo sin embargo. Si no necesita estos extras, wait() y notify() son una alternativa aceptable.

+0

Consulte mi pregunta editada: esta no es realmente una respuesta relevante. – ripper234

+0

Ok, luego puse una sugerencia de muestra para usar una nueva utilidad de alto nivel: Bloquear. –

0

Los métodos park() unpark() de la clase LockSupport parecen ser útiles en este caso. También me enfrenté a las mismas preguntas y mientras buscaba en la red, encontré una pista en esta discusión.

Synchronization vs Lock

Pero tienen que entender los conceptos más para crear una aplicación de ejemplo.

0

¿Qué le parece usar Semaphore del paquete Concurrent? ¿Utiliza un semáforo binario como un bloqueo intrínseco y dos semáforos de conteo para establecer un límite en el tamaño de la cola?

Cuestiones relacionadas