Maison >Java >javaDidacticiel >Introduction au mécanisme COW et aux classes associées
Le contenu de cet article est une introduction au mécanisme COW et aux classes associées. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Le mécanisme COW a des classes associées
Vector et SynchronizedList
Nous savons qu'ArrayList est utilisé pour remplacer Vector et Vector est un conteneur thread-safe. Parce qu'il ajoute le mot-clé synchronisé à presque toutes les déclarations de méthode pour sécuriser le conteneur. Si vous utilisez Collections.synchronizedList(new ArrayList()) pour rendre ArrayList thread-safe, presque toutes les méthodes ajouteront le mot-clé synchronisé, mais il n'est pas ajouté lors de la déclaration de la méthode, mais à l'intérieur de la méthode.
Sous l'itération de boucle for multithread de Vector ou SynchronizedList, une exception d'erreur d'indice de tableau se produira lors de l'exécution d'opérations de suppression et d'obtention.
Après JDK5, Java recommande d'utiliser for-each (itérateur) pour parcourir notre collection. L'avantage est que c'est simple et que la valeur limite de l'index du tableau n'est calculée qu'une seule fois. Si vous utilisez for-each (itérateur) pour effectuer l'opération ci-dessus, une ConcurrentModificationException sera levée.
Si nous voulons résoudre parfaitement le problème mentionné ci-dessus, nous pouvons ajouter un verrou avant de traverser :
Chaque fois que je traverse le conteneur, je dois ajouter un verrou, n'est-ce pas aussi. lent? . C'est effectivement assez lent. Parce que la granularité de verrouillage est trop grande.
CopyOnWriteArrayList remplace la liste synchrone et CopyOnWriteArraySet remplace la Set synchrone.
Hashtable et Vector ont une grande granularité de verrouillage (utilisation synchronisée directement lors de la déclaration de la méthode) ConcurrentHashMap et CopyOnWriteArrayList ont une petite granularité de verrouillage (utilisez diverses méthodes pour assurer la sécurité des threads, par exemple, nous savons que ConcurrentHashMap utilise cas lock , volatile et d'autres méthodes pour assurer la sécurité des threads..) Le conteneur thread-safe sous JUC ne lancera pas ConcurrentModificationException pendant la traversée. Donc, de manière générale, nous utiliserons le conteneur thread-safe qui nous est fourni dans le package JUC au lieu d'utiliser l'ancienne génération A. de conteneurs thread-safe.
Principe d'implémentation de CopyOnWriteArrayList
CopyOnWriteArrayList est un conteneur thread-safe (par rapport à ArrayList), et la couche inférieure est implémentée en copiant le tableau. CopyOnWriteArrayList ne lancera pas ConcurrentModificationException lors du parcours, et il n'est pas nécessaire de verrouiller des éléments supplémentaires pendant le parcours. L'élément peut être nul
/** 可重入锁对象 */ final transient ReentrantLock lock = new ReentrantLock(); /** CopyOnWriteArrayList底层由数组实现,volatile修饰 */ private transient volatile Object[] array; final Object[] getArray() { return array; } final void setArray(Object[] a) { array = a; } // 初始化CopyOnWriteArrayList相当于初始化数组 public CopyOnWriteArrayList() { setArray(new Object[0]); }
La couche inférieure de CopyOnWriteArrayList est un tableau et le verrouillage est effectué par ReentrantLock. .
Nous pouvons savoir grâce au code : verrouiller lors de l'ajout (), set (), supprimer () et copier un nouveau tableau, l'opération d'ajout est terminée sur le nouveau tableau et le tableau pointe vers le nouveau array , enfin débloqué. Lors de la modification, un nouveau tableau est copié, l'opération de modification est terminée dans le nouveau tableau et enfin le nouveau tableau est pointé par la variable tableau. Verrouillé pour l'écriture, non verrouillé pour la lecture
Inconvénients de CopyOnWriteArrayList
Utilisation de la mémoire : si CopyOnWriteArrayList ajoute, supprime et modifie souvent les données qu'il contient et exécute souvent add(), set(), et remove() , qui consomme plus de mémoire.
Parce que nous savons que chaque opération d'ajout, de suppression et de modification telle que add(), set() et remove() doit copier un tableau.
Cohérence des données : Le conteneur CopyOnWrite ne peut garantir que la cohérence finale des données, mais ne peut garantir la cohérence en temps réel des données.
Cela peut également être vu dans l'exemple ci-dessus, par exemple, le thread A itère les données du conteneur CopyOnWriteArrayList. Le thread B a modifié les données dans la partie CopyOnWriteArrayList pendant l'intervalle d'itération du thread A (setArray() a été appelé). Mais le thread A parcourt les données d'origine.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!