Mot clé synchronisé nested

J’ai ce code en Java:

public void doSomeThing() { synchronized (this) { doSomeThingElse(); } } public void doSomeThingElse() { synchronized (this) { // do something else } } 

Est-ce que ce code peut bloquer? Je veux dire, ce code peut-il attendre pour toujours?

Comme le décrit la documentation Java pour le locking Reentrant :

un thread peut acquérir un verrou qu’il possède déjà

Le deuxième bloc synchronisé utilise le même verrou et sera donc toujours utilisable car le verrou a déjà été acquis dans la méthode externe.

Non, il n’y aura pas d’impasse.

Si un thread possède le verrou, il utilisera d’autres méthodes / blocs synchronized comme un couteau chaud dans du beurre.

Dans un bloc synchronisé, vous pouvez réacquérir un verrou que vous possédez déjà. Le fournisseur de verrou (this) sera acquis par le premier thread pour entrer doSomething (). Ensuite, dans la méthode doSomethingElse (), il va le ré-acquérir.

La raison de faire ça? Eh bien, rien ne dit qu’il n’ya pas d’autre fil entrant dans doSomethingElse d’ailleurs. Cela empêchera tout code d’exécuter le bloc dans doSomething () jusqu’à ce que le thread dans doSomethingElse () ait libéré “this”.

Modifier BTW, il peut bien sûr bloquer … et il bloquera tout thread qui ne possède pas l’object de synchronisation de s’exécuter. Cependant, il ne sera pas (comme affiché) une impasse.

Verrou déjà obtenu par le thread qui exécute la méthode do quelque chose, donc ce thread peut exécuter la méthode doSomethingElse.

Vous avez besoin de deux objects de locking pour créer une situation de blocage. Dans votre cas, il n’y en a qu’un, il est donc impossible de créer une impasse.

L’utilisation synchronisée dans les deux cas, donc si le bloc synchronisé dans doSomeThing est exécuté, vous avez déjà le verrou afin que vous puissiez exécuter la méthode doSomeThingElse.

Si votre code est si simple, cela équivaut à:

 public synchronized void doSomeThing() { doSomeThingElse(); } public synchronized void doSomeThingElse() { // do something else } 

Vous avez déjà pris le locking du moniteur lors de la première synchronisation. Vous devez toujours vous assurer que la conception de la concurrence ne rend pas la performance importante.

Un moyen de garantir cela est de ne synchroniser que les instructions / codes requirejs.

Disons que votre code ressemblera à ceci.

 public void doSomeThing() { synchronized (this) { synchronized (this) { // do something else } } } 

Considérant que c’est ce qui est requirejs

 public void doSomeThing() { doSomeThingElse(); } public void doSomeThingElse() { synchronized (this) { // do something else } }