某个线程使用Iterator遍历该List时,若有另外一个线程对其修改,实际修改的是内存中的一份拷贝,对Iterator操作无影响,从而规避了
并发操作的问题。
缺点:
1、消耗更多的内存
优点:
1、在大量读操作的,改动操作较少的应用场景,可以规避阻塞,等待,提高读取效率;
注意区别读写锁,读写锁在写操作的时候,读操作是被阻塞的,只有读操作可以并发。
问题:
1、因为读/写在不同的内存块中进行,如果预期写入在读之前,即,预期读的数据包含要写入的数据,则可能因为racing condition导致
读不到期望的数据(例如写完成之前,读操作已经开始了)
例子:
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray(); //获取当前的ArrayList的数据
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); //拷贝到新的内存块中,多拷贝一块内存
newElements[len] = e; //将要添加的对象添加到新的内存块的结尾
setArray(newElements); //将新的内存块作为当前的ArrayList的数据源
return true;
} finally {
lock.unlock();
}
}
用到了Arrays.copyOf 方法。这样导致每次操作的都不是同一个引用。也就不会出现java.util.ConcurrentModificationException错误。
并发操作的问题。
缺点:
1、消耗更多的内存
优点:
1、在大量读操作的,改动操作较少的应用场景,可以规避阻塞,等待,提高读取效率;
注意区别读写锁,读写锁在写操作的时候,读操作是被阻塞的,只有读操作可以并发。
问题:
1、因为读/写在不同的内存块中进行,如果预期写入在读之前,即,预期读的数据包含要写入的数据,则可能因为racing condition导致
读不到期望的数据(例如写完成之前,读操作已经开始了)
例子:
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray(); //获取当前的ArrayList的数据
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); //拷贝到新的内存块中,多拷贝一块内存
newElements[len] = e; //将要添加的对象添加到新的内存块的结尾
setArray(newElements); //将新的内存块作为当前的ArrayList的数据源
return true;
} finally {
lock.unlock();
}
}
用到了Arrays.copyOf 方法。这样导致每次操作的都不是同一个引用。也就不会出现java.util.ConcurrentModificationException错误。