Question

Quelle est la différence entre un Collections.synchronizedMap () et une enveloppe autour d'une table de hachage avec toutes les méthodes synchronisées. Je ne vois aucune différence becuase Collections.synchronizedMap () maintient en interne le même verrou pour toutes les méthodes.

Au fond, quelle est la différence entre les extraits de code suivant

Class C {    
    Object o;

    public void foo() {
       synchronized(o) {
           // thread safe code here
       }
    }
}

et

Class C {
    Object o;

    public synchronized void foo() {

    }
}
Était-ce utile?

La solution

Il n'y a qu'une seule différence:

Collections.synchronizedMap est capable pour utiliser un autre moniteur que lui-même.

En utilisant des méthodes synchronisés est la même que l'utilisation de sychnchonized(this)-blocs, ce qui signifie, l'enveloppe serait le moniteur et peut être verrouillé depuis l'extérieur de l'enveloppe.

Si vous ne voulez pas une application extérieure pour verrouiller votre moniteur, vous devez le cacher.

De l'autre côté, si vous voulez appeler plusieurs méthodes dans un fil de façon sûre, il est la meilleure façon de verrouiller toute la collection (mais pas très échelonnable, en effet).

Ps. Pour la réutilisation, il est préférable de déléguer la méthode appelle à une sauvegarde carte que de passer outre la classe, parce que vous pouvez passer à une autre mise en œuvre de la carte plus tard, sans changer votre emballage

Autres conseils

Les deux approches acquièrent un moniteur sur l'objet et doivent donc effectuer exactement la même chose. La principale raison de la différence est architecturale. L'enveloppe synchronisée permet d'étendre la variation de base sûre non-fil facilement.

Cela dit ne pas utiliser non plus, utilisez ConcurrentHashMap. Il utilise striping serrure il est donc beaucoup plus rapide à utiliser que les deux approches (car ils sont les mêmes en termes de frais généraux + contention). l'entrelacement permet de verrouillage des segments de la matrice de support pour verrouiller de façon indépendante. Cela signifie qu'il est moins probable que deux fils demanderont d'acquérir le même verrou.

Ne pas réinventer la roue et utiliser ce qui est fourni par l'API.

Vous devez toujours décorer plutôt que amalgamant tout et tous Feartures dans une grande classe en vedette.

Prenez toujours la carte simple et décorer avec les collections ou utiliser un java.util.concurrent et utiliser un vrai verrou, on peut donc atomiquement inspecter et mettre à jour la carte. Demain vous pourriez vouloir changer le Hashtable à un Treemap et vous serez en difficulté si votre coincé avec une table de hachage.

Alors, pourquoi demandez-vous? :) Est-ce que vous croyez vraiment que si la classe est placé dans le paquet java.util alors un peu de magie se produit et son code Java fonctionne d'une manière délicate?

Il enveloppe vraiment juste toutes les méthodes avec bloc et rien synchronisé {} plus.

UPD: la différence est que vous avez beaucoup moins de chances de faire une erreur si vous utilisez la collection au lieu de faire synchronisé tous les trucs de synchronisation par vous-même

.

UPD 2: comme vous pouvez le voir dans les sources qu'ils utilisent « mutex'-objet comme moniteur. Lorsque vous utilisez le modificateur synchronisé dans la signature de la méthode (à savoir synchronized void doSmth()) instance actuelle de votre objet (à savoir this) est utilisé comme moniteur. Deux blocs de code ci-dessous sont les mêmes:

1.

synchronized public void doSmth () {
   someLogic ();
   moreLogic ();
}

synchronized public static void doSmthStatic () {
   someStaticLogic ();
   moreStaticLogic ();
}

2.

public void doSmth () {
   synchronized (this) {
      someLogic ();
      moreLogic ();
   }
}

public static void doSmthStatic () {
   synchronized (ClassName.class) {
      someStaticLogic ();
      moreStaticLogic ();
   }
}

Si la sécurité des threads est le cas, l'utilisation des structures de données de package d'accès concurrentiel. Utilisation de la classe d'emballage réduit tous les accès à la carte dans une file d'attente séquentielle.

a) les threads en attente d'effectuer des opérations à des points tout à fait différents dans la carte attendront le même verrou. En fonction du nombre de threads cela peut affecter les performances de l'application.

b) Examiner les opérations de composés sur la carte. L'utilisation d'un emballage avec un verrou unique ne sera pas utile. Par exemple. type d'opération « Regardez si présent puis ajouter ». Discussion syncronization redeviendra un problème.

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