Maison  >  Article  >  développement back-end  >  Explication détaillée de l'utilisation de synchronisé pour implémenter un code de verrouillage

Explication détaillée de l'utilisation de synchronisé pour implémenter un code de verrouillage

php中世界最好的语言
php中世界最好的语言original
2017-12-20 11:56:032479parcourir

Cet article présente comment utiliser synchronisé pour implémenter un code de verrouillage. Ce qui suit est un cas pratique. Les amis dans le besoin peuvent s'y référer.

Méthode 1 :

public synchronized void a(){
  //TODO
}


Méthode 2 :

public void b(){
  synchronized(this){
    //TODO
  }
}


D'ici Dans les deux cas, le verrou est ajouté entre {}. Voyons comment le verrouillage est effectué :

public void c() {
  lock.lock();
  try {
    // TODO
  } finally {
    lock.unlock();
  }
}


De cette façon, le verrou est ajouté entre lock(). et unlock(), donc si vous souhaitez implémenter une fonction de verrouillage, vous devez réfléchir à la façon d'implémenter ces deux méthodes, les méthodes lock() et unlock(). Définissez d'abord un frameworkComme indiqué ci-dessous :

public void lock(){
}
public void unlock(){
}


Ensuite, vous souhaitez utiliser synchronisé pour implémenter ces deux méthodes.

Maintenant, j'ai en fait une idée un peu plus claire, mais je ne sais toujours pas comment remplir ces deux méthodes. J'analyserai les caractéristiques de Lock plus tard et jetterai un œil à ce code :

public void c() {
    lock.lock();
    //When current thread get the lock, other thread has to wait
    try {
        //current thread get in the lock, other thread can not get in
        // TODO
    }
    finally {
        lock.unlock();
        //current thread release the lock
    }
}


Je viens d'ajouter un petit commentaire à ce code et je n'ai rien fait d'autre. Cela aide-t-il à comprendre ce code ? mot fréquent ? Il s'agit de currentthread. Alors, lorsque nous remplissons les méthodes lock() et unlock(), devons-nous faire attention au mot-clé currentthread pour trouver la solution ? La réponse est oui.

Ensuite, analysez, comment faire attendre le fil lors d'une utilisation synchronisée ? Utilisez la méthode wait(). Comment réveiller le thread ? Utilisez la méthode notify(). Utilisez ensuite la méthode wait() dans la méthode lock() et la méthode notify() dans la méthode unlock(). Il y a donc une condition lorsque nous utilisons wait() et notify(). Pensez à ce que nous devrions utiliser comme condition ?

Nous devrions utiliser si le verrou actuel est occupé comme condition de jugement. Si le verrou est occupé, currentthread attend. Demandez-vous si nous avons toujours utilisé cette condition lors de l'utilisation de synchronisé, la réponse est oui.

Analysons quand libérer le verrou et quelles conditions sont utilisées. Pensez-y. Si le thread A obtient le verrou, le thread B peut-il le libérer ? Bien sûr que non. Si B pouvait être libéré, cela violerait le principe. Il faut que le verrou du thread A ne puisse être libéré que par le thread A. La condition de jugement est donc de juger si le thread qui détient le verrou est le thread actuel. Si c'est le cas, il peut être libéré. ​​Sinon, bien sûr, il ne peut pas.

Jetons maintenant un œil au code complet :

package test.lock;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class NaiveLock {
    private static final long NONE = -1;
    private long owner = NONE;
    private Boolean isLooked() {
        return owner != NONE;
    }
    public synchronized void lock() {
        long currentThreadId = Thread.currentThread().getId();
        if (owner == currentThreadId) {
            throw new IllegalStateException("Lock has been acquired by current thread");
        }
        while (this.isLooked()) {
            System.out.println(String.format("thread %s is waitting lock", currentThreadId));
            try {
                wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        owner = currentThreadId;
        System.out.println(String.format("Lock is acquired by thread %s", owner));
    }
    public synchronized void unlock() {
        if (!this.isLooked() || owner != Thread.currentThread().getId()) {
            throw new IllegalStateException("Only Lock owner can unlock the lock");
        }
        System.out.println(String.format("thread %s is unlocking", owner));
        System.out.println();
        owner = NONE;
        notify();
    }
    public static void main(String[] args) {
        final NaiveLock lock = new NaiveLock();
        ExecutorService executor = Executors.newFixedThreadPool(20, new ThreadFactory() {
            private ThreadGroup group = new ThreadGroup("test thread group");
            {
                group.setDaemon(true);
            }
            @Override
                  public Thread newThread(Runnable r) {
                return new Thread(group, r);
            }
        }
        );
        for (int i = 0; i < 20; i++) {
            executor.submit(new Runnable() {
                @Override
                        public void run() {
                    lock.lock();
                    System.out.println(String.format("thread %s is running...", Thread.currentThread().getId()));
                    try {
                        Thread.sleep(new Random().nextint(1000));
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.unlock();
                }
            }
            );
        }
    }
}


Exécutez-le et voyez le résultat :

Lock is acquired by thread 8
thread 8 is running...
thread 27 is waitting lock
thread 26 is waitting lock
thread 25 is waitting lock
thread 24 is waitting lock
thread 23 is waitting lock
thread 22 is waitting lock
thread 21 is waitting lock
thread 20 is waitting lock
thread 19 is waitting lock
thread 18 is waitting lock
thread 17 is waitting lock
thread 16 is waitting lock
thread 15 is waitting lock
thread 14 is waitting lock
thread 13 is waitting lock
thread 12 is waitting lock
thread 11 is waitting lock
thread 10 is waitting lock
thread 9 is waitting lock
thread 8 is unlocking
  
Lock is acquired by thread 27
thread 27 is running...
thread 27 is unlocking
  
Lock is acquired by thread 26
thread 26 is running...
thread 26 is unlocking
  
Lock is acquired by thread 25
thread 25 is running...
thread 25 is unlocking
  
Lock is acquired by thread 24
thread 24 is running...
thread 24 is unlocking
  
Lock is acquired by thread 23
thread 23 is running...
thread 23 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 22 is unlocking
  
Lock is acquired by thread 21
thread 21 is running...
thread 21 is unlocking
  
Lock is acquired by thread 20
thread 20 is running...
thread 20 is unlocking
  
Lock is acquired by thread 19
thread 19 is running...
thread 19 is unlocking
  
Lock is acquired by thread 18
thread 18 is running...
thread 18 is unlocking
  
Lock is acquired by thread 17
thread 17 is running...
thread 17 is unlocking
  
Lock is acquired by thread 16
thread 16 is running...
thread 16 is unlocking
  
Lock is acquired by thread 15
thread 15 is running...
thread 15 is unlocking
  
Lock is acquired by thread 14
thread 14 is running...
thread 14 is unlocking
  
Lock is acquired by thread 13
thread 13 is running...
thread 13 is unlocking
  
Lock is acquired by thread 12
thread 12 is running...
thread 12 is unlocking
  
Lock is acquired by thread 11
thread 11 is running...
thread 11 is unlocking
  
Lock is acquired by thread 10
thread 10 is running...
thread 10 is unlocking
  
Lock is acquired by thread 9
thread 9 is running...
thread 9 is unlocking


Si vous modifiez la boucle for à 30 fois, regardez à nouveau le résultat :

Lock is acquired by thread 8
thread 8 is running...
thread 27 is waitting lock
thread 26 is waitting lock
thread 25 is waitting lock
thread 24 is waitting lock
thread 23 is waitting lock
thread 22 is waitting lock
thread 21 is waitting lock
thread 20 is waitting lock
thread 19 is waitting lock
thread 18 is waitting lock
thread 17 is waitting lock
thread 16 is waitting lock
thread 15 is waitting lock
thread 14 is waitting lock
thread 13 is waitting lock
thread 12 is waitting lock
thread 11 is waitting lock
thread 10 is waitting lock
thread 9 is waitting lock
thread 8 is unlocking
  
Lock is acquired by thread 27
thread 27 is running...
thread 8 is waitting lock
thread 27 is unlocking
  
Lock is acquired by thread 27
thread 27 is running...
thread 26 is waitting lock
thread 27 is unlocking
  
Lock is acquired by thread 27
thread 27 is running...
thread 25 is waitting lock
thread 27 is unlocking
  
Lock is acquired by thread 24
thread 24 is running...
thread 27 is waitting lock
thread 24 is unlocking
  
Lock is acquired by thread 23
thread 23 is running...
thread 24 is waitting lock
thread 23 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 23 is waitting lock
thread 22 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 21 is waitting lock
thread 22 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 20 is waitting lock
thread 22 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 19 is waitting lock
thread 22 is unlocking
  
Lock is acquired by thread 22
thread 22 is running...
thread 18 is waitting lock
thread 22 is unlocking
  
Lock is acquired by thread 17
thread 17 is running...
thread 17 is unlocking
  
Lock is acquired by thread 16
thread 16 is running...
thread 16 is unlocking
  
Lock is acquired by thread 15
thread 15 is running...
thread 15 is unlocking
  
Lock is acquired by thread 14
thread 14 is running...
thread 14 is unlocking
  
Lock is acquired by thread 13
thread 13 is running...
thread 13 is unlocking
  
Lock is acquired by thread 12
thread 12 is running...
thread 12 is unlocking
  
Lock is acquired by thread 11
thread 11 is running...
thread 11 is unlocking
  
Lock is acquired by thread 10
thread 10 is running...
thread 10 is unlocking
  
Lock is acquired by thread 9
thread 9 is running...
thread 9 is unlocking
  
Lock is acquired by thread 8
thread 8 is running...
thread 8 is unlocking
  
Lock is acquired by thread 26
thread 26 is running...
thread 26 is unlocking
  
Lock is acquired by thread 25
thread 25 is running...
thread 25 is unlocking
  
Lock is acquired by thread 27
thread 27 is running...
thread 27 is unlocking
  
Lock is acquired by thread 24
thread 24 is running...
thread 24 is unlocking
  
Lock is acquired by thread 23
thread 23 is running...
thread 23 is unlocking
  
Lock is acquired by thread 21
thread 21 is running...
thread 21 is unlocking
  
Lock is acquired by thread 20
thread 20 is running...
thread 20 is unlocking
  
Lock is acquired by thread 19
thread 19 is running...
thread 19 is unlocking
  
Lock is acquired by thread 18
thread 18 is running...
thread 18 is unlocking


Je pense que vous maîtrisez les méthodes après avoir lu ces cas. Pour des informations plus intéressantes, veuillez prêter attention aux autres articles connexes sur le site Web chinois de php !

Lecture connexe :

Exemple de code détaillé de la façon dont PHP implémente la structure de données de pile et l'algorithme de correspondance entre crochets

Le plus populaire code en PHP Algorithme de correspondance de chaînes simple, algorithme de correspondance php_Tutoriel PHP

Le tutoriel d'algorithme de correspondance de chaînes le plus simple en php

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn