CopyOnWriteArrayListでのsetメソッド追記
3270 ワード
最近ずっと同時プログラミングネットワークを見ていますが、この文章はまずこの場所の理解を記録します.
コンテキスト環境移行CopyOnWriteArrayListクラスsetメソッド疑惑?
[java] view plain copy print ?
/** The array, accessed only via getArray/setArray. */
private volatile transient Object[] array;
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
setメソッドではelse判定に空の操作setArrayがあるように見え,読み出した配列をまた値付けに戻した.
この場所には、単一スレッドでもマルチスレッドでもelementsの結果や読み出しのelementに影響を及ぼさないものがあるかどうか、長い間見てやっとその意味が理解できたようです.
ここで注釈に注意して、volatileが意味を書くことを保証します.この言葉を理解するにはjavaの命令の再配置とhappens beforeの原則を理解しなければなりません.
同時プログラミングネットワークにもいくつかの文章が解釈されており、詳細はhappens-beforeの俗解と「二重検査ロックの失効」に関する説明に移行している.
ここでsetArrayを呼び出すと,setメソッドhappens beforeがgetメソッドにあることが主に保証される.
スレッド1
スレッド2
setメソッドにそのような一言がない、list[1]がもともと「t」である場合、ここでは命令の再配置によりlist.get(0)の取得はtであるが,bの取得は1ではない.
次に、cloneの新しいオブジェクトを参照する理由を説明します.
getArrayやiteratorなど、setの前に古いオブジェクトへの参照が得られる場合には干渉せず、CopyOnWriteArrayListは読み取り操作が多い場合に使用され、書き込み操作性能が劣る.可変オブジェクトをパブリッシュするには、さらなる同期操作は必要ありません.これはCopyOnWriteの核心的な考え方です.
上の二重チェックロックが無効になった問題ここでも、主な問題は、参照されたコマンドとオブジェクト初期化の割り当てにオブジェクトが割り当てられる可能性があるコマンドを並べ替え、getInstanceがオブジェクトを取得したときに初期化に失敗したオブジェクト属性を表示することです.単一のリファレンスにvolatile修飾子を付けると、リファレンス割り当てが完了したときにオブジェクトコンストラクション関数の割り当てが完了することが保証されます.
遅延初期化の一例の方式は、クラスを使用するときに初期化され、同時問題が発生しない占有クラス方式を採用して実現するより良い考え方がある.
もう少し詳しく知る必要があるような気がしますが、理解が間違っているところがあれば指摘してください.ありがとうございます.
コンテキスト環境移行CopyOnWriteArrayListクラスsetメソッド疑惑?
[java] view plain copy print ?
/** The array, accessed only via getArray/setArray. */
private volatile transient Object[] array;
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
setメソッドではelse判定に空の操作setArrayがあるように見え,読み出した配列をまた値付けに戻した.
この場所には、単一スレッドでもマルチスレッドでもelementsの結果や読み出しのelementに影響を及ぼさないものがあるかどうか、長い間見てやっとその意味が理解できたようです.
ここで注釈に注意して、volatileが意味を書くことを保証します.この言葉を理解するにはjavaの命令の再配置とhappens beforeの原則を理解しなければなりません.
同時プログラミングネットワークにもいくつかの文章が解釈されており、詳細はhappens-beforeの俗解と「二重検査ロックの失効」に関する説明に移行している.
ここでsetArrayを呼び出すと,setメソッドhappens beforeがgetメソッドにあることが主に保証される.
スレッド1
スレッド2
1
a =
1
;
2
list.set(
1
,
"t"
);
1
list.get(
0
);
2
int
b = a;
setメソッドにそのような一言がない、list[1]がもともと「t」である場合、ここでは命令の再配置によりlist.get(0)の取得はtであるが,bの取得は1ではない.
次に、cloneの新しいオブジェクトを参照する理由を説明します.
getArrayやiteratorなど、setの前に古いオブジェクトへの参照が得られる場合には干渉せず、CopyOnWriteArrayListは読み取り操作が多い場合に使用され、書き込み操作性能が劣る.可変オブジェクトをパブリッシュするには、さらなる同期操作は必要ありません.これはCopyOnWriteの核心的な考え方です.
上の二重チェックロックが無効になった問題ここでも、主な問題は、参照されたコマンドとオブジェクト初期化の割り当てにオブジェクトが割り当てられる可能性があるコマンドを並べ替え、getInstanceがオブジェクトを取得したときに初期化に失敗したオブジェクト属性を表示することです.単一のリファレンスにvolatile修飾子を付けると、リファレンス割り当てが完了したときにオブジェクトコンストラクション関数の割り当てが完了することが保証されます.
遅延初期化の一例の方式は、クラスを使用するときに初期化され、同時問題が発生しない占有クラス方式を採用して実現するより良い考え方がある.
public class ResourceFactory{
private static class ResourceHolder{
public static Resource resource = new Resource();
}
public static Resource getResource(){
return ResourceHolder.resource;
}
}
もう少し詳しく知る必要があるような気がしますが、理解が間違っているところがあれば指摘してください.ありがとうございます.