J'ai jeté un oeil dans OpenJDK source code de CopyOnWriteArrayList
et il semble que toutes les opérations d'écriture sont protégées par le même verrou et les opérations de lecture ne sont pas protégées du tout. Si je comprends bien, sous JMM tous les accès à une variable (à la fois en lecture et en écriture) doivent être protégés par des verrous ou des effets de réorganisation peuvent se produire.Comment CopyOnWriteArrayList peut-il être thread-safe?
Par exemple, la méthode set(int, E)
contient ces lignes (sous les verrous):
/* 1 */ int len = elements.length;
/* 2 */ Object[] newElements = Arrays.copyOf(elements, len);
/* 3 */ newElements[index] = element;
/* 4 */ setArray(newElements);
La méthode get(int)
, d'autre part, seulement return get(getArray(), index);
. Dans ma compréhension de JMM, cela signifie que get
peut observer le tableau dans un état incohérent si les instructions 1-4 sont réordonnées comme 1-2 (nouveau) -4-2 (copyOf) -3.
Est-ce que je comprends mal JMM ou existe-t-il d'autres explications sur pourquoi CopyOnWriteArrayList
est thread-safe?
Merci. J'ai raté le fait que le tableau est "volatile". – Fixpoint
Un détail important est que volatile ne s'applique qu'à la référence du tableau elle-même, et non au contenu du tableau. Cependant, comme toutes les modifications apportées au tableau sont effectuées ** avant ** sa référence est publiée, les garanties volatiles s'étendent au contenu du tableau. – assylias