¿Hay un Mutex en Java?


¿Hay un objeto Mutex en java o una forma de crear uno? Estoy preguntando porque un objeto semáforo inicializado con 1 permiso no me ayuda. 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 es un semáforo binario.

¿Será el camino correcto?

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

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

Author: Prince, 2011-03-13

8 answers

Ver 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ás llamando a release() después de un acquire()

 99
Author: payne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-11 16:42:22

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

Object someObject = ...;

synchronized (someObject) {
  ...
}

Puedes leer más sobre esto aquí: Bloqueos intrínsecos y Sincronización

 115
Author: casablanca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-13 17:25:54
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();
 23
Author: Argv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-20 10:35:14

Creo que deberías probar con:

Mientras que la inicialización del 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);
}
 4
Author: Sashi Kant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-04 11:50:39

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 desea el subproceso propietario que originalmente bloqueado para poder desbloquear. Para este caso de uso, en Java, solemos usar ReentrantLocks, que se pueden crear así:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

private final Lock lock = new ReentrantLock(true);

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

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

Aquí es un ejemplo en la código fuente java donde se puede ver este patrón en acción.

Los bloqueos de reentrada tienen el beneficio añadido de apoyar la equidad.

Use semáforos solo si necesita semántica de liberación sin propiedad.

 4
Author: rouble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-03 15:05:39

Para asegurarse de que un Semaphore es 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.

 1
Author: Sanjay T. Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-13 18:50:24

El error en el post original es la llamada acquire() establecida dentro del bucle try. Aquí hay un enfoque correcto para usar semáforo "binario" (Mutex):

semaphore.acquire();
try {
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}
 1
Author: smile-on,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-01 05:28:23

El bloqueo de cada objeto es poco diferente del diseño Mutex/Semáforo. Por ejemplo, no hay manera de implementar correctamente atravesar nodos vinculados liberando el bloqueo del nodo anterior y capturando el 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 hay tal clase en java.util.concurrent, pero puede encontrar la implementación de Mutext aquí Mutex.java . En cuanto a las bibliotecas estándar, Semaphore proporciona toda esta funcionalidad y mucho más.

 1
Author: pogrebniuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-05 15:13:34