Maison >Java >JavaBase >Quelle est la différence entre synchronisé et verrouillé ?

Quelle est la différence entre synchronisé et verrouillé ?

青灯夜游
青灯夜游original
2020-11-19 11:38:2968740parcourir

Différences : 1. Lock est une interface et synchronisé est un mot-clé en Java. 2. Synchronisé libérera automatiquement le verrou qu'il détient lorsqu'une exception se produit, donc un blocage ne se produira pas ; lorsqu'une exception se produit, synchronisé ne libérera pas activement le verrou qu'il détient et le verrou doit être libéré manuellement, ce qui peut provoquer un blocage.

Quelle est la différence entre synchronisé et verrouillé ?

Dans le développement distribué, les verrous sont un moyen important de contrôler les threads. Java fournit également deux mécanismes de verrouillage à cet effet, synchronisé et verrouillé.

0. Principe de mise en œuvre synchronisé

Chaque objet en Java peut être utilisé comme un verrou, qui est la base de la synchronisation pour réaliser la synchronisation :

  • Méthode de synchronisation commune, le verrou est l'objet d'instance actuel

  • Méthode de synchronisation statique, le verrou est l'objet de classe de la classe actuelle

  • Bloc de méthode de synchronisation, le verrou est l'objet entre parenthèses
    Lorsqu'un thread accède à un bloc de code synchronisé, il doit d'abord obtenir le verrou. Lorsqu'il quitte ou lève une exception, il doit libérer le verrou. Alors, comment met-il en œuvre ce mécanisme ? Examinons d'abord un simple morceau de code :

package cn.alibab.javap;public class SynchronizedTest {

    public synchronized void test1(){

    }    public void test2(){        synchronized (this){

        }
    }
}

Utilisez l'outil javap (javap est un décomposeur de fichiers de classe après compilation Java) pour afficher les informations du fichier de classe généré afin d'analyser l'implémentation. de synchronisé

Quelle est la différence entre synchronisé et verrouillé ?

Quelle est la différence entre synchronisé et verrouillé ?
Comme le montre ce qui précède, le bloc de code de synchronisation est implémenté à l'aide des instructions monitorenter et monitorexit La méthode de synchronisation (c'est le cas. pas évident ici que vous devez examiner l'implémentation sous-jacente de la JVM) s'appuie sur l'implémentation ACC_SYNCHRONIZED sur le modificateur de méthode.

Bloc de code synchronisé : L'instruction Monitorenter est insérée au début du bloc de code synchronisé après la compilation, et l'instruction Monitorexit est insérée à la fin du bloc de code synchronisé dont la JVM a besoin. pour s'assurer que chaque entrée de moniteur a une sortie de moniteur qui lui correspond. Tout objet est associé à un moniteur. Lorsqu'un moniteur est maintenu, il sera dans un état verrouillé. Lorsque le thread exécute l'instruction monitorenter, il tentera d'obtenir la propriété du moniteur correspondant à l'objet, c'est-à-dire qu'il tentera d'obtenir le verrou de l'objet [Extrait de The Art of Concurrent Programming]

; Méthode synchronisée  : La méthode synchronisée sera traduite en instructions d'appel de méthode ordinaires et de retour telles que : instructions d'invocation virtuelle et de retour. Il n'y a pas d'instructions spéciales au niveau du bytecode de la VM pour implémenter la méthode modifiée par synchronisé. , la méthode est ajoutée à la table des méthodes du fichier Class. La position de l'indicateur synchronisé dans le champ access_flags est 1, indiquant que la méthode est une méthode synchronisée et utilise l'objet qui appelle la méthode ou la classe à laquelle la méthode appartient. représente la classe dans l'objet interne de la JVM en tant qu'objet de verrouillage. (Extrait de : http://www.cnblogs.com/javaminer/p/3889023.html)

La différence entre synchronisé et verrouillé

Quelle est la différence entre synchronisé et verrouillé ?
La différence est la suivante :

  • Source :
    lock est une interface, et synchronisé est un mot-clé de Java, synchronisé est une implémentation de langage intégrée

    ;
  • S'il faut libérer le verrou en raison d'une exception :
    synchronisé libérera automatiquement le verrou qu'il détient lorsqu'une exception se produit, il n'y aura donc pas de blocage lorsqu'une exception se produit, le verrouillage ne sera pas actif ; libérez le verrou qu'il détient et vous devez déverrouiller manuellement pour libérer le verrou, ce qui peut provoquer un blocage. (Il est donc préférable d'envelopper le bloc de code de synchronisation avec try catch et write unlock enfin pour éviter l'apparition d'un blocage.)

  • S'il faut répondre à l'interruption
    le verrou attend le verrou Vous pouvez utiliser l'interruption pour interrompre l'attente, mais la synchronisation ne peut qu'attendre que le verrou soit libéré et ne peut pas répondre aux interruptions

  • Savez-vous s'il faut acquérir le verrou ; lock?
    Lock peut utiliser trylock pour savoir si le verrou a été acquis. Synchronisé ne peut pas

  • Lock peut améliorer l'efficacité des opérations de lecture par plusieurs threads. (La séparation en lecture et en écriture peut être obtenue grâce au readwritelock)

  • En termes de performances, si la concurrence pour les ressources n'est pas féroce, les performances des deux sont presque les mêmes, mais lorsque le La concurrence pour les ressources est très féroce (c'est-à-dire qu'un grand nombre de threads sont en concurrence en même temps). À l'heure actuelle, les performances de Lock sont bien meilleures que celles de la synchronisation. Par conséquent, lorsque vous l’utilisez, vous devez le choisir en fonction de la situation appropriée.

  • synchronized utilise les mécanismes de planification wait, notify et notifyAll de l'objet Object lui-même, tandis que Lock peut utiliser Condition pour planifier entre les threads,

//Condition定义了等待/通知两种类型的方法
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();...condition.await();...condition.signal();
condition.signalAll();

1. La différence entre l'utilisation de synchronisé et de verrouillage

synchronisé : ajouter ce contrôle à l'objet qui doit être synchronisé peut être ajouté à la méthode ou à un spécifique. bloc de code, crochets Indique l'objet qui doit être verrouillé.

lock : Généralement, la classe ReentrantLock est utilisée comme verrou. Les emplacements de verrouillage et de déverrouillage doivent être affichés via lock() et unlock(). Par conséquent, unlock() est généralement écrit dans le bloc final pour éviter un blocage.

2. La différence de performances entre synchronisé et verrouillé

synchronisé est gérée par la JVM pour l'exécution,
et le verrouillage est un code écrit en Java pour contrôler le verrouillage.

En Java1.5, la synchronisation est inefficace en termes de performances. Comme il s'agit d'une opération lourde qui nécessite l'appel de l'interface d'opération, le verrouillage peut consommer plus de temps système que les opérations autres que le verrouillage. En revanche, l'utilisation de l'objet Lock fourni par Java offre des performances plus élevées.

Mais avec Java 1.6, les choses ont changé. Synchronize est très clair en termes de sémantique et peut effectuer de nombreuses optimisations, notamment la rotation adaptative, l'élimination des verrous, le grossissement des verrous, les verrous légers, les verrous biaisés, etc. En conséquence, les performances de synchronisation sur Java1.6 ne sont pas pires que celles de Lock. Les responsables ont également déclaré qu'ils prenaient également davantage en charge la synchronisation et qu'il y avait place à l'optimisation dans les versions futures.

Les différences spécifiques entre les deux mécanismes :
synchronisé utilisait à l'origine le mécanisme de verrouillage pessimiste du CPU, c'est-à-dire que le thread obtient un verrou exclusif. Le verrouillage exclusif signifie que les autres threads ne peuvent compter que sur le blocage pour attendre que le thread libère le verrou. Lorsque le thread de conversion du processeur est bloqué, cela entraînera un changement de contexte de thread. Lorsqu'il y a de nombreux threads en compétition pour le verrou, cela entraînera un changement de contexte fréquent du processeur, ce qui entraînera une très faible efficacité.

Lock utilise le verrouillage optimiste. Le verrouillage dit optimiste consiste à terminer une opération sans verrouiller à chaque fois, mais en supposant qu'il n'y a pas de conflit. Si elle échoue en raison d'un conflit, elle sera réessayée jusqu'à ce qu'elle réussisse. Le mécanisme mis en œuvre par le verrouillage optimiste est l'opération CAS (Compare and Swap). Nous pouvons étudier plus en détail le code source de ReentrantLock et constater que l’une des méthodes les plus importantes pour obtenir le verrou est compareAndSetState. Il s'agit en fait de l'instruction spéciale fournie par le processeur appelé.

Les processeurs modernes fournissent des instructions qui peuvent automatiquement mettre à jour les données partagées et détecter les interférences d'autres threads, et compareAndSet() les utilise à la place des verrous. Cet algorithme est appelé algorithme non bloquant, ce qui signifie que l'échec ou la suspension d'un thread ne doit pas affecter l'échec ou la suspension des autres threads.

3. La différence entre l'utilisation synchronisée et verrouillée

Il n'y a aucune différence entre la primitive synchronisée et ReentrantLock dans des circonstances normales, mais dans les applications de synchronisation très complexes, veuillez envisager d'utiliser ReentrantLock, en particulier lorsque vous rencontrez les deux exigences suivantes.

1. Un thread doit être interrompu en attendant le contrôle d'un verrou
2. Certaines notifications d'attente doivent être traitées séparément. L'application Condition dans ReentrantLock peut contrôler quel thread doit notifier
. 3. Avec la fonction de verrouillage équitable, chaque thread entrant fera la queue pour attendre

Parlons-en en détail ci-dessous...

Parlons d'abord du premier cas. Il existe deux mécanismes de verrouillage. de ReentrantLock , ignore les verrous d'interruption et répond aux verrous d'interruption, ce qui nous donne beaucoup de flexibilité. Par exemple : si deux threads A et B sont en compétition pour un verrou, le thread A obtient le verrou et le thread B attend. Cependant, le thread A a vraiment trop de choses à gérer à ce moment-là et ne pourra peut-être pas revenir. attendre plus longtemps. Je veux m'interrompre, arrêter d'attendre ce verrou et passer à autre chose. A ce moment ReentrantLock fournit 2 mécanismes : interruptible/non-interruptible
Premièrement, le thread B s'interrompt (ou d'autres threads l'interrompent), mais ReentrantLock ne répond pas et continue de laisser le thread B attendre , peu importe la façon dont vous l'interrompez, je l'ignorerai (c'est la primitive synchronisée
Deuxièmement, le thread B s'interrompt (ou d'autres threads l'interrompent), ReentrantLock gère l'interruption et n'attend plus le verrou Come , abandonnez complètement.

Pour plus de connaissances sur la programmation, veuillez visiter : Vidéo de programmation ! !

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