web-dev-qa-db-fra.com

Existe-t-il un mutex en Java?

Existe-t-il un objet Mutex dans Java ou un moyen d'en créer un? Je demande parce qu'un objet Semaphore initialisé avec 1 permis ne m'aide pas. Pensez à ce cas:

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

si une exception se produit lors de la première acquisition, la libération dans le bloc catch augmentera les autorisations et le sémaphore n'est plus un sémaphore binaire.

Est-ce que la voie correcte sera?

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

Le code ci-dessus garantira-t-il que le sémaphore sera binaire?

104
Noam Nevo

Voir cette page: http://www.Oracle.com/technetwork/articles/javase/index-140767.html

Il a un motif légèrement différent qui est (je pense) ce que vous recherchez:

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

Dans cette utilisation, vous n’appelez que release() après une opération réussie acquire()

109
payne

Tout objet de Java peut être utilisé comme verrou à l'aide d'un bloc synchronized. Cela permettra également de libérer automatiquement le verrou lorsqu'une exception se produit.

Object someObject = ...;

synchronized (someObject) {
  ...
}

Vous pouvez en savoir plus à ce sujet ici: Verrous Intrinsèques et Synchronisation

127
casablanca
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
Argv

Personne n’a clairement mentionné cela, mais ce type de motif ne convient généralement pas aux sémaphores. La raison en est que any thread peut libérer un sémaphore, mais vous ne voulez généralement que le thread propriétaire que verrouillé à l'origine pour pouvoir le déverrouiller . Pour ce cas d'utilisation, en Java, nous utilisons généralement ReentrantLocks, qui peut être créé comme suit:

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

private final Lock lock = new ReentrantLock(true);

Et le modèle de conception habituel d'utilisation est:

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

Here est un exemple dans le code source Java où vous pouvez voir ce modèle en action.

Les serrures réentrantes ont l'avantage supplémentaire de favoriser l'équité.

Utilisez des sémaphores uniquement si vous avez besoin d'une sémantique ne libérant pas la propriété.

7
rouble

Je pense que vous devriez essayer avec:

Pendant l’initialisation du sémaphore:

Semaphore semaphore = new Semaphore(1, true);

Et dans votre Runnable Implementation

try 
{
   semaphore.acquire(1);
   // do stuff

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}
5
Sashi Kant

Une erreur dans le message d'origine est un appel à acquérir () défini dans la boucle try. Voici une approche correcte pour utiliser le sémaphore "binaire" (Mutex):

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

Pour vous assurer que Semaphore est binaire, il vous suffit de spécifier le nombre de permis égal à 1 lors de la création du sémaphore. Les Javadocs ont un peu plus d'explications.

1
Sanjay T. Sharma

Le verrou de chaque objet est un peu différent de la conception Mutex/Semaphore. Par exemple, il n'y a aucun moyen de mettre en œuvre correctement les nœuds liés traversants en relâchant le verrou du nœud précédent et en capturant le prochain. Mais avec mutex, il est facile à implémenter:

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();
} 

Actuellement, il n'y a pas de classe de ce type dans Java.util.concurrent, mais vous pouvez trouver l'implémentation de Mutext ici Mutex.Java . Semaphore fournit toutes ces fonctionnalités et bien plus encore.

1
pogrebniuk