Les Collections.synchronizedList et synchronisés
List<String> list = Collections.synchronizedList(new ArrayList<String>());
synchronized (list) {
list.add("message");
}
Est le bloc "synchronisée (liste){}" vraiment besoin ici ?
Vous devez vous connecter pour publier un commentaire.
Vous n'avez pas besoin de synchroniser que vous mettez dans votre exemple. CEPENDANT, très important, vous avez besoin de synchroniser autour de la liste quand vous de le parcourir (comme indiqué dans la Javadoc):
Cela dépend du contenu exact de la
synchronized
bloc:Si le bloc effectue une seule opération atomique sur la liste (comme dans votre exemple), la
synchronized
est superflu.Si le bloc effectue plusieurs opérations sur la liste -- et les besoins pour maintenir le verrou pour la durée de la concession de l'opération -- le
synchronized
est pas superflu. Un exemple courant de ce est de parcourir la liste.Le code sous-jacent pour les Collections.synchronizedList ajouter de la méthode est la suivante:
Donc dans votre exemple, il n'est pas nécessaire d'ajouter de la synchronisation.
Également Important de noter que toutes les méthodes qui utilisent les Itérateurs par exemple des Collections.sort() devra également être encapsulé à l'intérieur d'un bloc synchronisé.
Lire ce Oracle Doc
Il dit: "Il est impératif que l'utilisateur de synchroniser manuellement sur la liste retournée lors de l'itération sur elle"
Comme ce qui a été mentionné par d'autres, le synchronisée collections sont thread-safe, mais le composé des actions de ces collections ne sont pas garantis pour être thread-safe par défaut.
Selon JCIP, la commune composé d'actions peuvent être
L'OP est synchronisée bloc de code n'est pas un composé de l'action, donc pas de différence si l'ajouter ou pas.
Prenons l'exemple de JCIP et de le modifier un peu pour expliquer pourquoi il est nécessaire de garde le composé des actions avec serrure.
Il y a deux méthodes qui fonctionnent sur la même collection
list
qui a enveloppé parCollections.synchronizedList
Si les méthodes
getLast
etdeleteLast
sont appelés en même temps par deux threads différents, au-dessous des feuilles intercalaires peuvent se produire etgetLast
va jeterArrayIndexOutOfBoundsException
. Supposons actuellastIndex
est de 10.Thread (deleteLast) --> supprimer
Le fil B (getLast) --------------------> get
Le Fil d'Une
remove
l'élément avant de laget
opération dans le Thread B. Ainsi, le Thread B toujours utiliser 10 commelastIndex
appelerlist.get
méthode, cela conduira à la simultanées problème.