ejemplo java mutex semaphore java.util.concurrent concurrent-programming

ejemplo - ¿Hay un Mutex en Java?



producer consumer java semaphore (8)

¿Hay un objeto Mutex en Java o una forma de crear uno? Pregunto porque un objeto Semaphore inicializado con 1 permiso no me sirve. Piensa en este caso:

try { semaphore.acquire(); //do stuff semaphore.release(); } catch (Exception e) { semaphore.release(); }

si ocurre una excepción en la primera adquisición, la liberación en el bloque catch aumentará los permisos, y el semáforo ya no será un semáforo binario.

¿Será la forma correcta?

try { semaphore.acquire(); //do stuff } catch (Exception e) { //exception stuff } finally { semaphore.release(); }

¿El código anterior asegurará que el semáforo será binario?


Consulte esta página: http://www.oracle.com/technetwork/articles/javase/index-140767.html

Tiene un patrón ligeramente diferente que es (creo) lo que estás buscando:

try { mutex.acquire(); try { // do something } finally { mutex.release(); } } catch(InterruptedException ie) { // ... }

En este uso, solo está llamando a release() después de una acquire() exitosa acquire()


Creo que deberías probar con:

Mientras se inicia el semáforo:

Semaphore semaphore = new Semaphore(1, true);

Y en su Runnable Implementation

try { semaphore.acquire(1); // do stuff } catch (Exception e) { // Logging } finally { semaphore.release(1); }


Cualquier objeto en Java se puede usar como un bloqueo usando un bloque synchronized . Esto también se encargará automáticamente de liberar el bloqueo cuando ocurra una excepción.

Object someObject = ...; synchronized (someObject) { ... }

Puede leer más sobre esto aquí: bloqueos intrínsecos y sincronización


El bloqueo de cada objeto es poco diferente del diseño Mutex / semáforo. Por ejemplo, no hay forma de implementar correctamente los nodos vinculados con la liberación del bloqueo del nodo anterior y la captura del siguiente. Pero con mutex es fácil de implementar:

Node p = getHead(); if (p == null || x == null) return false; p.lock.acquire(); // Prime loop by acquiring first lock. // If above acquire fails due to interrupt, the method will // throw InterruptedException now, so there is no need for // further cleanup. for (;;) { Node nextp = null; boolean found; try { found = x.equals(p.item); if (!found) { nextp = p.next; if (nextp != null) { try { // Acquire next lock // while still holding current nextp.lock.acquire(); } catch (InterruptedException ie) { throw ie; // Note that finally clause will // execute before the throw } } } }finally { // release old lock regardless of outcome p.lock.release(); }

Actualmente, no existe dicha clase en java.util.concurrent , pero puede encontrar la implementación de Mutex.java aquí Mutex.java . En cuanto a las bibliotecas estándar, Semaphore ofrece toda esta funcionalidad y mucho más.


El error en la publicación original es el conjunto de llamadas adquirido () dentro del ciclo de prueba. Aquí hay un enfoque correcto para usar semáforos "binarios" (Mutex):

semaphore.acquire(); try { //do stuff } catch (Exception e) { //exception stuff } finally { semaphore.release(); }


Nadie ha mencionado esto claramente, pero este tipo de patrón generalmente no es adecuado para semáforos. La razón es que cualquier subproceso puede liberar un semáforo, pero normalmente solo quieres que el subproceso propietario que se bloqueó originalmente pueda desbloquearse . Para este caso de uso, en Java, normalmente usamos ReentrantLocks, que se puede crear de esta manera:

import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; private final Lock lock = new ReentrantLock(true);

Y el patrón de uso de diseño habitual es:

lock.lock(); try { // do something } catch (Exception e) { // handle the exception } finally { lock.unlock(); }

Here hay un ejemplo en el código fuente de Java donde puede ver este patrón en acción.

Las cerraduras reentrantes tienen el beneficio adicional de apoyar la equidad.

Use semáforos solo si necesita una semántica que no sea de propiedad.


Para garantizar que un Semaphore sea ​​binario, solo necesita asegurarse de pasar el número de permisos como 1 al crear el semáforo. Los Javadocs tienen un poco más de explicación.


import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; private final Lock _mutex = new ReentrantLock(true); _mutex.lock(); // your protected code here _mutex.unlock();