80 votes

Comment synchroniser ou verrouiller des variables en Java ?

Permettez-moi d'utiliser ce petit et simple échantillon :

 class Sample {
    private String msg = null;

    public void newmsg(String x){
        msg = x;
    }

    public String getmsg(){
        String temp = msg;
        msg = null;
        return temp;
    }
}

Supposons que la fonction newmsg() soit appelée par d'autres threads auxquels je n'ai pas accès.

Je souhaite utiliser la méthode de synchronisation pour garantir que la chaîne msg n'est utilisée que par une fonction à la fois. En d'autres termes, la fonction newmsg() ne peut pas s'exécuter en même temps que getmsg() .

184voto

Jon Skeet Points 692016

C'est assez simple :

 class Sample {
    private String message = null;
    private final Object lock = new Object();

    public void newMessage(String x) {
        synchronized (lock) {
            message = x;
        }
    }

    public String getMessage() {
        synchronized (lock) {
            String temp = message;
            message = null;
            return temp;
        }
    }
}

Notez que je n'ai ni synchronisé les méthodes elles-mêmes ni synchronisées sur this . Je crois fermement que c'est une bonne idée de n'acquérir des verrous que sur des objets auxquels seul votre code a accès, à moins que vous n'exposiez délibérément le verrou. Il est beaucoup plus facile de vous rassurer que rien d'autre ne va acquérir des verrous dans un ordre différent de votre code, etc.

60voto

Peter Lawrey Points 229686

Pour cette fonctionnalité, il vaut mieux ne pas utiliser de verrou du tout. Essayez une référence atomique.

 public class Sample {
    private final AtomicReference<String> msg = new AtomicReference<String>();

    public void setMsg(String x) {
        msg.set(x);
    }

    public String getMsg() {
        return msg.getAndSet(null);
    }
}

Aucune serrure requise et le code est plus simple à mon humble avis. Dans tous les cas, il utilise une construction standard qui fait ce que vous voulez.

10voto

Niclas Meier Points 176

Depuis Java 1.5, c'est toujours une bonne idée de considérer le package java.util.concurrent. Ils sont le mécanisme de verrouillage de pointe en Java en ce moment. Le mécanisme de synchronisation est plus lourd que les classes java.util.concurrent.

L'exemple ressemblerait à ceci :

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

public class Sample {

    private final Lock lock = new ReentrantLock();

    private String message = null;

    public void newmsg(String msg) {
        lock.lock();
        try {
            message = msg;
        } finally {
            lock.unlock();
        }
    }

    public String getmsg() {
        lock.lock();
        try {
            String temp = message;
            message = null;
            return temp;
        } finally {
            lock.unlock();
        }
    }
}

3voto

gd1 Points 5430

Dans cet exemple simple, vous pouvez simplement mettre synchronized comme modificateur après public dans les deux signatures de méthode.

Des scénarios plus complexes nécessitent d'autres éléments.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X