Question

Quelle pourrait être la compréhension de ce qui suit?
Je suis passé par ce poste au SO, mais encore à une perte pour l'assembler.

code1:

synchronized(this){ 
// some code
}

code2:

Object lock = new Object();

synchronized(lock){
// some code
}

Tout tutoriel ou des liens à expliquer synchronisés comme ils l'expliquent à un enfant?

Était-ce utile?

La solution

Une chose non mentionné dans les réponses par ailleurs excellent déjà donné est la différence entre code1 et code2. Dans code1, la synchronisation est de l'instance de l'objet dans lequel le code est détecté, et en code2, il est l'objet spécifique de verrouillage à l'intérieur de l'objet.

S'il n'y a que les deux blocs synchronisés dans la classe englobante, il n'y a pas fonctionnel différence entre les deux, mais considérez ceci:

class CodeOneClass {
  ...
  synchronized(this) {   // or merely "synchronized" - it defaults to this
      first protected code block
  }
  ...
  synchronized(this) {   
      second protected code block
  }
...
}

class CodeTwoClass {
  ...
  Object lock1 = new Object();
  synchronized(lock1) {   
      first protected code block
  }
  ...
  Object lock2 = new Object();
  synchronized(lock2) {   
      second protected code block
  }
...
}

Si deux threads tentent d'utiliser la même instance de CodeOneClass, un seul d'entre eux peut être ou l'autre des deux blocs de code protégés en même temps.

Mais avec le deuxième idiome, vous avez la possibilité de dire qu'il est sûr pour un fil d'être dans le premier bloc protégé, et un autre pour être dans l'autre. Notez que si les serrures étaient les mêmes (à la fois la synchronisation sur le même objet de verrouillage), le comportement serait que le premier.

Il existe d'autres différences. Certains auteurs commencent à signaler des problèmes avec synchronisé (ce) - Je vous pointer vers un autre poste ici sur le SO: Évitez synchronisées (cela) en Java?

Je recommande fortement la lecture, et les trois postes vers lesquels il pointe.

Autres conseils

en substance, une « serrure » associée à chaque objet en Java.

Quand un thread atteint un appel à synchronisé (quelque chose), il doit acquérir le verrou de quelque chose avant de continuer. Si vous souhaitez autoriser un seul thread à la fois de modifier l'état d'un objet, la chose la plus évidente est de synchroniser le verrouillage de cet objet. Si différentes méthodes sont autorisés à être appelés verrous parallèle, vous avez besoin de différents pour cela.

Si vous écrivez synchronized (this), ou tout simplement synchronisé, le fil doit acquérir le verrou associé à l'objet courant (de la méthode qui est appelée).

Notez que depuis Java 5.0, il package concurrent fournit bon serrures qui peuvent être utilisés à la place de la synchronisation.

Code Mettre dans un bloc de synchronized signifie essentiellement, « Une fois ce code commence à courir, tout autre code qui doit utiliser cet objet ne peut pas exécuter en même temps. »

Donc, si cette discussion n ° 2 est l'exécution de code dans votre bloc code2, en ce qui concerne le code synchronized(lock) il doit chercher efficacement autour de tous les autres threads pour vous assurer que personne d'autre est en cours d'exécution du code « synchronisé » avec l'objet lock en ce moment. Discussion # 1 est certainement en cours d'exécution certains Code en même temps, mais il pourrait être un code complètement différent. Si oui, il est sans danger pour la discussion n ° 2 pour commencer à courir vos affaires « de some code ».

En attendant, si cette discussion n ° 1 arrive au bloc synchronized(this), il a trop de faire une pause et de voir si d'autres threads utilisent this. Si this est le même objet que lock, nous avons un problème. On nous a dit qu'un seul thread peut éventuellement utiliser cet objet (dans un bloc synchronisé) en même temps. Pourtant, cette discussion # 2 est déjà l'utiliser. Discussion # 1 aura juste à attendre ... et attendre ... et attendre ... jusqu'à ce que finalement Enfilez # 2 finitions. Ensuite, nous pouvons continuer.

Le résultat final est que seul un bloc de synchronized peut fonctionner à la fois (avec un objet particulier, bien sûr).

Supposons que vous avez un objet Account qui a une méthode:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   if (accountBalance >= debitAmount) {
      accountBalance -= debitAmount;
      beneficiary.credit(debitAmount);
   }
   else {
      throw new InsufficientFundsException();
   }
}

Supposons maintenant que vous avez un compte avec un solde de 100 euros, et vous obtenez deux tentatives de débiter par 70 euros. Si les deux débits se produisent en même temps, vous pouvez obtenir un race condition comme ceci:

  • chèques du premier débit solde du compte: 100> = 70, donc réussit
  • Deuxième contrôle de débit solde du compte: 100> = 70, donc réussit
  • exécute d'abord de débit; le solde du compte devient 30
  • Deuxième débit exécute; le solde du compte est -40. Ne doit pas être autorisé

Nous pouvons empêcher cette situation désastreuse des affaires en synchronisant sur le verrouillage de l'objet Account:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   synchronized (this) {
      if (accountBalance >= debitAmount) {
         accountBalance -= debitAmount;
         beneficiary.credit(debitAmount);
      }
      else {
         throw new InsufficientFundsException();
      }
   }
}

Ceci assure que le test sur le solde du compte et le débit ne peut être interrompu par un autre test sur le solde du compte.

Le tutoriel Sun Java est un bon endroit pour commencer des informations sur le verrouillage et la concurrence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top