Statiques et non statiques de verrouillage de l'objet dans le bloc synchronisé
Essayer de visualiser et de comprendre synchronisation.
- Quelles sont les différences entre l'utilisation d'un statique de verrouillage objet (code) et un non statique de verrouillage objet (code B) pour un synchronisé bloc?
- Comment est-il différent dans les applications pratiques?
- Quels sont les obstacles qu'on aurait que l'autre ne le serait pas?
- Quels sont les critères pour déterminer lequel utiliser?
Code Un
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Code B
public class MyClass2 {
private final Object lock = new Object();
public MyClass2() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Note
Le code ci-dessus montre les constructeurs, mais vous pourriez parler de la façon dont le comportement est différent dans une méthode statique et non méthode statique trop. Aussi, serait-il avantageux d'utiliser un statique de verrouillage lors de la synchronisation de bloc est de la modification d'une variable membre statique?
Je l'ai déjà regardé les réponses dans cette question, mais c'est pas assez clair sur ce que les différents scénarios d'utilisation sont.
- "Notez que le code ci-dessus montre les constructeurs," C'est une distinction importante. Un bloc synchronisé avec un champ d'instance sur un constructeur est absolument inutile, car aucun les deux fils ne sera jamais exécuter un constructeur sur la même instance.
- En fait, à bien y penser, cette instance pourrait contient un objet qui est partagé entre les threads. Par exemple
private final Object lock = "niceLiteralString";
. - Je comprends l'aide de constructeurs de montrer l'exemple était une mauvaise idée. Ma question s'étend à statiques et non statiques et méthodes. Aussi, comment ne partage de la statique/champ d'instance affecter le verrouillage?
- "comment fonctionne le partage de la statique/champ d'instance affecter le verrouillage?" La serrure n'est pas sur le terrain, mais sur l'instance de l'objet que le champ contient. Donc
synchronized (a){}; synchronized(b){}; synchronized(c){}
pourrait tous se retrouver à l'aide de la même serrure. Ils peuvent également lancer des NullPointerExceptions, si le champ est null. - cet article en fait l'argument que les littéraux de Chaîne doit être évitée pour une bonne raison - la réutilisation des références par la JVM.
- C'était juste un exemple pour illustrer le fait que même si votre domaine est privé, l'objet qu'il contient peut-être pas.
Vous devez vous connecter pour publier un commentaire.
La différence est simple: si la immobilisé sur un objet se trouve dans un
static
champ, puis toutes les instances deMyClass*
sera partager que de serrure (par exemple, pas deux objets seront en mesure de bloquer sur cet objet à la même heure).Si le champ n'est pas statique, chaque instance aura son propre cadenas, de sorte que seuls les appels de la méthode sur le même objet verrouiller les uns des autres.
Lorsque vous utilisez un statique de verrouillage de l'objet:
o1.foo()
o1.foo()
, devra attendre pour le thread 1 finitiono2.foo()
, sera aussi avoir à attendre pour le thread 1 (et probablement 2) pour terminerLorsque vous utilisez un non-statique de verrouillage de l'objet:
o1.foo()
o1.foo()
, devra attendre pour le thread 1 finitiono2.foo()
, il peut juste continuer, n'hésite pas thread 1 et 2Laquelle l'un de ces, vous aurez besoin dépend du type de données que vous essayez de protéger avec votre bloc synchronisé.
En règle générale, vous souhaitez que le lock-objet pour avoir la même
static
-ness que les exploité-sur la valeur. Donc, si vous manipulez des non-valeurs statiques seulement, vous aurez envie d'une non-statique de verrouillage de l'objet. Si vous manipulez des valeurs statiques seulement, vous aurez envie d'une statique de verrouillage de l'objet.Lorsque vous manipulez statiques et non statiques valeurs, puis ça va devenir compliqué. Le facile façon serait de simplement utiliser un verrou d'objet statique, mais qui pourrait augmenter la taille de la synchronisation de bloc de plus que ce qui est absolument nécessaire et pourrait avoir besoin de plus de verrous que souhaité. Dans ces cas, vous pourriez avoir besoin d'une combinaison de statiques et non statiques verrouiller des objets.
Dans votre cas particulier, vous utilisez le verrou dans le constructeur, qui ne pourront jamais être exécutée une fois par instance, de sorte qu'un non-statique lock-objet n'a pas de sens ici.
++
sur unint
**** vous ne se soucient pas de l'ordre (c'est à dire que vous n'avez pas de soins si vous avez lu avant ou après l'opération).x++
n'est pas atomique sur un volatile x. Faire aller de l'avant et de poser une nouvelle question pour cela.