この記事の内容は COW の仕組みと関連クラスの紹介であり、一定の参考価値がありますので、困っている方は参考にしていただければ幸いです。
COW メカニズムには関連クラスがあります
Vector と SynchronizedList
ArrayList は Vector の置き換えに使用され、Vector はスレッドセーフなコンテナーであることがわかっています。コンテナを安全にするために、ほぼすべてのメソッド宣言に synchronized キーワードが追加されるからです。 Collections.synchronizedList(new ArrayList()) を使用して ArrayList をスレッドセーフにする場合、ほぼすべてのメソッドで synchronized キーワードが追加されますが、これはメソッドの宣言ではなくメソッド内部で追加されます。
Vector または SynchronizedList のマルチスレッド for ループ反復では、削除および取得操作を実行すると、配列添字エラー例外が発生します。
JDK5 以降、Java では、コレクションの走査に for-each (反復子) を使用することが推奨されています。利点は、それが簡単で、配列インデックスの境界値が 1 回だけ計算されることです。 for-each (イテレータ) を使用して上記の操作を実行すると、ConcurrentModificationException がスローされます。
上記の問題を完全に解決したい場合は、トラバースする前にロックを追加できます:
コンテナをトラバースするときにロックを追加する必要があります。遅い? 。確かにかなり遅いです。ロックの粒度が大きすぎるためです。
CopyOnWriteArrayList は同期 List の代替であり、CopyOnWriteArraySet は同期 Set の代替です。
Hashtable と Vector はロックの粒度が大きい (メソッド宣言で直接同期を使用する) ConcurrentHashMap と CopyOnWriteArrayList はロックの粒度が小さい (スレッド セーフを実現するためにさまざまなメソッドを使用する。たとえば、ConcurrentHashMap は cas lock 、 volatile を使用することがわかっています) JUC のスレッド セーフ コンテナは、トラバーサル中に ConcurrentModificationException をスローしません。したがって、一般的に言えば、古い A 世代を使用する代わりに、JUC パッケージで提供されるスレッド セーフ コンテナを使用します。スレッドセーフなコンテナーの。
CopyOnWriteArrayList の実装原理
CopyOnWriteArrayList は (ArrayList に対して) スレッドセーフなコンテナーであり、最下層は配列をコピーすることによって実装されます。 CopyOnWriteArrayList はトラバース時に ConcurrentModificationException をスローせず、トラバース中に追加の要素をロックする必要はありません。要素は null にすることができます
/** 可重入锁对象 */ 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]); }
CopyOnWriteArrayList の最下層は配列であり、ロックは ReentrantLock によって行われます。
コードから次のことがわかります。add()、set()、remove()、および新しい配列のコピー時にロックされ、新しい配列で加算操作が完了し、配列が新しい配列をポイントします。配列 、ついにロックが解除されました。変更する場合、新しい配列がコピーされ、新しい配列内で変更操作が完了し、最後に新しい配列が配列変数によってポイントされます。書き込み用にロックされ、読み取り用にロックされない
CopyOnWriteArrayList の欠点
メモリ使用量: CopyOnWriteArrayList がデータの追加、削除、変更を頻繁に行い、add()、set() を頻繁に実行する場合、および Remove() は、より多くのメモリを消費します。
add()、set()、remove() などの各追加、削除、変更操作では配列をコピーする必要があることがわかっているためです。
データの一貫性: CopyOnWrite コンテナはデータの最終的な一貫性のみを保証できますが、データのリアルタイムの一貫性は保証できません。
上記の例からもわかります。たとえば、スレッド A は CopyOnWriteArrayList コンテナーのデータを反復しています。スレッド B は、スレッド A の反復ギャップ中に CopyOnWriteArrayList 部分のデータを変更しました (setArray() が呼び出されました)。ただし、スレッド A は元のデータを反復処理します。
以上がCOW メカニズムと関連クラスの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。