En entrant dans synchronisé bloc atomique?

savez-vous s'il est garanti que le bloc synchronisé en java est atomique?

imaginez le cas suivant

Thread_1, 2:

synchronized(object){object.modify();}

(l'objet est une variable partagée.)

imaginez thread_M va changer la référence à un objet comme

synchronized(object){object = new Object()}

imaginez maintenant que les threads 1 et 2 sont en compétition pour obtenir le verrouillage sur l'objet

est-il possible que

1. Thread1: lire ancien objet

2. ThreadM: modifier la référence d'objet et la libération de l'ancien objet de verrouillage

3. Thread2: lire un nouvel objet; vérifier le verrouillage; le verrouiller

4. Thread1: vérification de verrouillage (ok cos ancien objet a été lu); verrouiller sur elle

maintenant les deux threads ont une serrure et modifier le même objet (nouveau)

donc pour préciser ma question - Est quelque part garantie que dans les étapes(objet) synchronisées (1 et 4) sont atomiques (comme décrit à l'étape 3)?

3
demandé sur Vit Bernatik 2015-03-23 21:03:43

3 réponses

vous can réattribuez object pendant que vous êtes synchronisé sur object , mais je ne peux pas penser à un scénario où la réattribution d'un champ utilisé pour le verrouillage est une bonne idée.

aucun autre thread ne pourra acquérir la serrure sur l'ancienne valeur de object jusqu'à ce que thread m sorte de son bloc synchronisé, mais un autre thread pourra acquérir une serrure sur le nouvel objet dès qu'il sera visible à ce thread.

Les Modifications faites par un thread avant de libérer une serrure sont garanties pour être visibles aux threads qui acquièrent la serrure après. Mais puisque vous réassignez la serrure elle-même, le thread d'acquisition peut ne pas voir qu'elle a été changée, et acquérir une serrure sur l'ancienne valeur. Alors ils ne verraient toujours pas que object a été réaffecté.

déclarer object comme variable volatile permettrait de s'assurer que sa valeur "courante" est utilisée pour le verrouillage. Mais il ne serait pas empêcher deux threads de modifier la même instance simultanément:

  1. le fil M se verrouille sur l'ancienne valeur. Thread 1 lit l'ancienne valeur.
  2. Thread m change la valeur.
  3. Thread m déverrouille l'ancienne valeur. Thread 2 lit la nouvelle valeur.
  4. Thread 1 acquiert un verrou sur l'ancienne valeur. Thread 2 acquiert une nouvelle valeur.
  5. Thread 1 lit new value. Fil 2 lit nouvelle valeur.
  6. Thread 1 modifie la nouvelle valeur. Thread 2 modifie une nouvelle valeur.

pour éviter tout cela, il suffit de créer un objet séparé pour le verrouillage, et ne jamais le changer.

1
répondu erickson 2015-03-23 19:09:11

supposons que vous ayez une variable, foo :

Foo foo;

Et supposons qu'il contient une référence à un objet:

foo = new Foo(...);

et supposons que nous ayons un bloc synchronized :

synchronized(foo) {
    ...
}

le synchronized keywoord ne pas fonctionne sur la variable, foo , et il ne pas fonctionne sur les déclarations dans le bloc synchronisé.

la seule chose que le mot-clé synchronized fait ici est d'empêcher les autres threads de se synchroniser sur la même instance en même temps.

si vous réassignez la variable, foo pour faire référence à une instance différente alors que le thread A est à l'intérieur du bloc, alors un autre thread B pourra entrer dans le même bloc en même temps parce que chacun des deux threads sera synchronisé sur une instance différente.

2
répondu Solomon Slow 2015-03-23 18:56:16

vous êtes en train de synchroniser l'objet vers lequel" l'objet " pointe, et non la variable contenant la valeur.

cependant, parce que les deux morceaux de code se synchronisent sur votre objet avant d'aller de l'avant, vous êtes en sécurité -- bien que ce soit un mauvais modèle de conception.

vous pouvez trouver moins de confusion si vous utilisez des méthodes synchronisées au lieu de blocs de code synchronisés.

aussi, à mon avis, mais synchronisé (objet) semble comme un Mauvaise conception de modèle. C'est juste mon opinion, mais je ne fais jamais quelque chose comme ça.

0
répondu Joseph Larson 2015-03-23 18:09:34