web-dev-qa-db-fra.com

objet synchronisé défini sur null

J'ai deux threads Thread1 et Thread2

//Within Thread1     
synchronized(obj1)  
{  
    obj1 = null;  
}  

//Within Thread2  
synchronized(obj1)  
{  
    do something  
}   

Si jvm exécute d'abord thread1 et définit obj1 sur null, alors thread2 verra ce changement immédiatement ou cela prendra du temps et jvm pourra toujours exécuter le bloc thread2 synchronisé puisque obj1 n'est pas encore nul

22
vjk

Cela rompra presque certainement l'abstraction de la synchronisation - je ne serais pas sûr que thread2 verra le changement immédiatement. Vous ne devriez jamais changer la référence de l'objet sur lequel vous synchronisez, et encore moins le définir sur null, ce qui entraînera une NullPointerException lors de toute nouvelle tentative de synchronisation sur cet objet.

33
Louis Wasserman

Permettez-moi tout d’abord de souligner que la modification d’une variable utilisée pour la synchronisation est une très mauvaise chose ™. obj1 devrait être final et ne jamais être touché s'il est utilisé comme moniteur.

Cela étant dit, revenons à votre question:

Si la machine virtuelle Java exécute pour la première fois Thread1, elle se synchronise sur obj1, la définit sur null et le thread se ferme. Le deuxième thread veut se synchroniser sur obj1, NullPointerException sera levé. Étant donné que la modification de obj1 a été effectuée dans un bloc synchronisé, il est garanti que Thread2 verra la valeur mise à jour (donc: NullPointerException est garanti).

Si Thread1 est interrompu après avoir obtenu le verrou sur obj1 mais avant d'effacer la référence, Thread2 se verrouille sur obj1 et attend la fin de Thread1. Il entrera ensuite avec succès dans le moniteur car l'objet précédemment référencé par obj1 existe toujours.

12
Tomasz Nurkiewicz

synchronized se synchronise sur l'objet et non sur la référence. En définissant obj1 (une référence) sur null, thread2 ne peut pas se synchroniser sur l'objet précédemment désigné par obj1, vous obtiendrez plutôt une NullPointerException.

4
Steve Kuo

Le changement est immédiat. Lorsque le thread 1 "possède" le verrou, il peut changer la valeur de obj1 à volonté. Le thread 2 doit attendre que le thread 1 lâche le verrou. Vous verrez certainement obj1 == null

1
mprivat

Une solution rapide consiste à transformer l'objet en un tableau simple de 1 élément et à faire référence au tableau pour la synchronisation, par exemple:

Object [] obj1 = {null};

L'élément peut être null sans impacter l'existence du tableau. Certes, cela brise toujours la "règle" de ne pas utiliser l'objet lui-même en synchronisation, mais à moins que votre code ne complique les choses ailleurs, cette solution rapide devrait fonctionner comme prévu.

1
Jerry Miller