Vector或Collections.synchronizedList为什么get方法要加锁?CopyOnWriteArrayList并没有。
我觉得读的时候不加锁应该没问题吧?读时候加锁有什么意义?能确保读到最新值?那么直接给Object[] elementData
加volatile
关键字保证可见性。
我也知道CopyOnWriteArrayList修改是每次重新建一个elementData
,但就算不是重新建,读时不加锁有什么问题?请赐教。
//以下是CopyOnWriteArrayList的代码:
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
//以下是Vector的代码:
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
Each thread in Java has its own working memory, which can be understood as a copy of a part of the main memory. If volatile is used, it can only guarantee that it is immediately readable on the main memory, and cannot guarantee atomic synchronization with the working memory of each thread
Even if volatile is not used, but only synchronized is added to the write operation, but not to the read operation, there is not only the problem of not being able to read the latest value, the bigger problem is the synchronization of the thread working memory and the main memory. Imagine the following situation:
Integer i = 0
a thread gives i+1
While a is performing this +1 operation, thread b reads i into its own working memory. At this time, i is still 0 because the read is not locked
a thread is executed, i = 1, and then synchronized to main memory
b performs a +1 operation on i. Since a has released the write lock, b can write, but since i in its own working memory is 0, i is still 1 after +1
bThe operation is completed and synchronized to the main memory. The i of the main memory is still 1. But in fact I hope i is 2