2012-09-21 2 views
1

J'ai utilisé les blocs synchronized de Java pour sécuriser certaines parties de mon thread de code. Je porte une structure de données à Java qui peut habituellement utiliser des blocs synchronized, mais je ne sais pas toujours comment les utiliser de manière Java typique.Comment verrouiller sous Java?

Voici un exemple d'un scénario:

myMethod (Bool useLock) 
    { 
    if (useLock) 
     { 
     //locks the following section of code until unlocked. 
     lockObject.lock(); 
     } 

    //do more stuff.... 

    if (useLock) 
     { 
     //unlocks exclusive control of code. 
     lockObject.unlock(); 
     } 
    } 

Comment puis-je faire un équivalent de ce en Java? Dans ce code, parfois je veux verrouiller et parfois je ne veux pas, mais je veux être intelligent à ce sujet et ne pas avoir à écrire deux versions du même code. Existe-t-il d'autres façons de verrouiller Java que d'utiliser des blocs synchronized?

Répondre

4

Vous pouvez utiliser des objets Lock, ReentrantLock en particulier devrait faire le travail. Vous pouvez toujours résoudre le problème avec synchronized blocs. Le code de votre question ressemblera:

myMethod (Bool useLock) { 
    if (useLock) { 
     synchronized (this) { 
      criticalSection(); 
     } 
    } else { 
     criticalSection(); 
    } 
} 

criticalSection() { 
    //do more stuff.... 
} 

Ou si vous voulez garantir l'exclusion mutuelle entre les différentes instances de la classe, vous devez utiliser un autre objet de moniteur que this. Par exemple TheClassName.class ou autre variable statique explicitement définie de cette classe.

+0

Il a déjà spécifié un objet à verrouiller: 'lockObject'. Et 'Bool' n'est pas une classe Java standard. – m0skit0

+0

J'ai fini par utiliser votre solution synchronisée. J'ai regardé dans ReentrantLock, alors merci! Mais ils ne semblent pas être mutuellement exclusifs aux blocs synchronisés. – Jon

1

Vous pouvez utiliser Unsafe pour monitorEnter et monitorExit mais c'est une mauvaise idée IMHO.

Si les verrous ne sont pas nécessaires, la JVM les optimisera presque dans tous les cas. synchronized est très efficace si un seul thread l'acquiert. (Contrairement à Lock par exemple)

1

Existe-t-il d'autres façons de verrouiller Java que d'utiliser des blocs synchronisés?

Oui - en particulier java.util.concurrent.locks et la classe ReentrantLock mais comme Peter dit que si vous pouvez vous en sortir avec juste en utilisant synchronized il sera probablement plus efficace (et plus facile à maintenir l'ensemble, en particulier si vous travaillez dans le cadre d'une équipe).

2

Je suppose que ReentrantLock peut être utilisé dans votre scénario

final Lock lock = new ReentrantLock(); 

Exemple de code extrait

class X { 
private final ReentrantLock lock = new ReentrantLock(); 
// ... 

public void m() { 
    lock.lock(); // block until condition holds 
    try { 
    // ... method body 
    } finally { 
    lock.unlock() 
    } 
    } 
} 
1

Vous pouvez utiliser des objets Java lock et Condition objets. Condition docs java de classe donne un très bon exemple isFull et isEmpty aussi.

Dans votre cas, je suppose, vous pouvez utiliser l'objet de condition pour rendre le code plus lisible/compréhensible. quelque chose comme ceci:

final Lock lock = new ReentrantLock(); 
final Condition useLock = lock.newCondition(); 

et d'utiliser la condition comme approprié.

1

Quelques bonnes réponses déjà affichées, mais je voulais ajouter une autre solution qui a fonctionné pour moi:

J'ai commencé avec:

... 
synchronized(<lockobject>) { 
<huge section of code with lots of variables> 
} 
... 

Changé à:

... 
synchronized(<condition> ? <lockobject> : new Object()) { 
<huge section of code with lots of variables> 
} 
... 

Fondamentalement, si la condition est vraie, il exécute le code en utilisant synchronized sur lockobject, mais si la condition est fausse, il utilise "new Object()" qui le laisse fonctionner sans aucune synchronisation.

Questions connexes