Si j'ai synchronisé deux méthodes sur la même classe, peuvent-elles s'exécuter simultanément sur le même objet ? par exemple:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
Je sais que je ne peux pas courir methodA()
deux fois sur le même objet dans deux threads différents. même chose en methodB()
.
Mais puis-je exécuter methodB()
sur un thread différent pendant qu'il methodA()
est toujours en cours d'exécution? (même objet)
obj.methodB()
est synonyme deA.methodB()
quandmethodB()
eststatic
. Donc oui, ils bloqueront (sur le moniteur de la classe, pas de l'objet)..class
objet. Donc si vous avezclass A {static synchronized void m() {} }
. Et puis un thread l'appellenew A().m()
acquiert un verrou sur l'new A()
objet. Si puis un autre thread appelleA.m()
ce CONCLUT LA MÉTHODE PAS DE PROBLÈME parce que ce qu'il cherche est verrou sur l'A.class
objet en NO FILETS possèdent ce type de serrure . Donc, même si vous avez déclaré la méthode,synchronized
elle est en fait accessible par deux threads différents EN MÊME TEMPS . Ainsi: ne jamais utiliser de références d'objet pour appeler des méthodes statiquesDans l'exemple, methodA et methodB sont des méthodes d'instance (par opposition aux méthodes statiques). Mettre
synchronized
sur une méthode d'instance signifie que le thread doit acquérir le verrou (le "verrou intrinsèque") sur l'instance d'objet sur laquelle la méthode est appelée avant que le thread ne puisse commencer à exécuter le code de cette méthode.Si vous avez deux méthodes d'instance différentes marquées comme synchronisées et que des threads différents appellent ces méthodes simultanément sur le même objet, ces threads seront en compétition pour le même verrou. Une fois qu'un thread obtient le verrou, tous les autres threads sont exclus de toutes les méthodes d'instance synchronisées sur cet objet.
Pour que les deux méthodes s'exécutent simultanément, elles devraient utiliser des verrous différents, comme ceci:
où la syntaxe du bloc synchronisé permet de spécifier un objet spécifique dont le thread en cours d'exécution a besoin pour acquérir le verrou intrinsèque afin d'entrer dans le bloc.
La chose importante à comprendre est que même si nous mettons un mot-clé «synchronisé» sur des méthodes individuelles, le concept de base est le verrou intrinsèque dans les coulisses.
Voici comment le didacticiel Java décrit la relation:
Le but du verrouillage est de protéger les données partagées. Vous utiliseriez des verrous séparés comme indiqué dans l'exemple de code ci-dessus uniquement si chaque verrou protégeait des membres de données différents.
la source
static synchronized
ousynchronized (A.class)
Java Thread acquiert un verrou au niveau de l'objet lorsqu'il entre dans une méthode Java synchronisée par instance et acquiert un verrou au niveau de la classe lorsqu'il entre dans une méthode Java synchronisée statique .
Dans votre cas, les méthodes (instance) sont de même classe. Ainsi, chaque fois qu'un thread entre dans la méthode synchronisée java ou dans un bloc, il acquiert un verrou (l'objet sur lequel la méthode est appelée). Donc, une autre méthode ne peut pas être appelée en même temps sur le même objet jusqu'à ce que la première méthode soit terminée et que le verrouillage (sur l'objet) soit libéré.
la source
private final Object lock = new object();
avec synchronized pour permettre à un seul thread de pouvoir exécuter l'une des méthodes? MerciDans votre cas, vous avez synchronisé deux méthodes sur la même instance de classe. Ainsi, ces deux méthodes ne peuvent pas s'exécuter simultanément sur différents threads de la même instance de classe A. Mais elles le peuvent sur différentes instances de classe A.
est le même que:
la source
private final Object lock = new Object();
et que je l' utilise maintenantlock
avec un bloc synchronisé dans deux méthodes, votre déclaration sera-t-elle vraie? IMO puisque Object est la classe parente de tous les objets, donc même si les threads sont sur une instance différente de la classe, un seul peut accéder au code à l'intérieur du bloc synchronisé à la fois. Merci.À partir du lien de documentation d'Oracle
La synchronisation des méthodes a deux effets:
Cela répondra à votre question: sur le même objet, vous ne pouvez pas appeler la deuxième méthode synchronisée lorsque la première exécution de la méthode synchronisée est en cours.
Consultez cette page de documentation pour comprendre les verrous intrinsèques et le comportement des verrous.
la source
Pensez à votre code comme ci-dessous:
Donc, synchronisé au niveau de la méthode signifie simplement synchronisé (ceci). si un thread exécute une méthode de cette classe, il obtiendrait le verrou avant de démarrer l'exécution et le maintiendrait jusqu'à ce que l'exécution de la méthode soit terminée.
En effet, ce n'est pas possible!
Par conséquent, plusieurs threads ne pourront pas exécuter un nombre quelconque de méthodes synchronisées sur le même objet simultanément.
la source
Pour toute clarté, il est possible que les méthodes synchronisées statiques et non statiques puissent s'exécuter simultanément ou simultanément, car l'une d'entre elles a un verrouillage au niveau de l'objet et un autre verrouillage au niveau de la classe.
la source
L' idée clé de la synchronisation qui ne s'enfonce pas facilement est qu'elle n'aura d'effet que si les méthodes sont appelées sur la même instance d' objet - elle a déjà été mise en évidence dans les réponses et les commentaires -
Ci-dessous l'exemple de programme est de clairement identifier le même
Notez la différence dans la sortie de la façon dont l'accès simultané est autorisé comme prévu si les méthodes sont appelées sur différentes instances d'objet.
Ouput avec noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects () commenté -la sortie est dans l'ordre methodA in> methodA Out .. methodB in> methodB Out
et Ouput avec synchronizedEffectiveAsMethodsCalledOnSameObject () commenté - la sortie montre l'accès simultané de methodA par Thread1 et Thread0 dans la section en surbrillance -
L'augmentation du nombre de threads le rendra encore plus visible.
la source
Non, ce n'est pas possible, si cela était possible, les deux méthodes pourraient mettre à jour la même variable simultanément, ce qui pourrait facilement corrompre les données.
la source
Oui, ils peuvent exécuter simultanément les deux threads. Si vous créez 2 objets de la classe car chaque objet contient un seul verrou et chaque méthode synchronisée nécessite un verrou. Donc, si vous souhaitez exécuter simultanément, créez deux objets, puis essayez de l'exécuter en utilisant ces références d'objet.
la source
Vous le synchronisez sur un objet et non sur une classe. Donc ils ne peuvent pas courir simultanément sur le même objet
la source
Deux threads différents exécutant une méthode synchronisée commune sur l'objet unique, puisque l'objet est le même, lorsqu'un thread l'utilise avec une méthode synchronisée, il devra varifier le verrou, si le verrou est activé, ce thread passera à l'état d'attente, si le verrou est désactivé, il peut accéder à l'objet, tandis qu'il y accédera, il activera le verrou et ne le libérera que lorsque son exécution sera terminée. lorsque l'autre thread arrive, il variera le verrou, puisqu'il est activé, il attendra que le premier thread termine son exécution et libère le verrou mis sur l'objet, une fois le verrou libéré, le deuxième thread aura accès à l'objet et il activera le verrou jusqu'à son exécution. donc l'exécution ne sera pas simultanée, les deux threads s'exécuteront un par un,
la source