java - 在 CopyOnWriteArrayList 中获取添加操作的锁
问题描述
为什么我们在添加元素时需要Reentrant
按照下面的代码获取锁。我们正在创建原始数组的副本,然后对其进行修改。如果我们一开始就没有获得,我们会有什么副作用?CopyOnWriteArrayList
List
lock
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
解决方案
当您尝试在多线程上下文中对全局变量执行任何操作并希望它是原子的并确保对其他线程的内存可见性时,您需要对该操作进行锁定。
这里getArray()
返回一个全局实例字段Object[] array
。
所以在这个例子中:
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
如果这个代码块周围没有锁,并且假设两个线程正在尝试添加一个元素,那么在这种情况下,线程一和线程二可能都会读取相同的值len
并将新元素分配给相同的索引。
因此,哪个线程在最后分配新值将覆盖另一个线程之前设置的值。
为了进一步解释,假设线程一和线程二都读取了相同的值,len
现在线程一继续创建新数组Arrays.copyOf(elements, len + 1)
,并将变量的值分配到新数组e
的len
位置。
在线程一可以使用setArray(newElements)
线程二设置新数组之前,同时使用相同的值继续这个过程len
。虽然它会创建一个新的数组实例,但设置新元素的索引将与len
线程一使用的索引相同。
因此,当线程二setArray(newElements)
在线程一之后使用新值设置新数组时,len
第 th索引处较早的数组值将被线程二设置的新元素覆盖。
推荐阅读
- javascript - 如何在 Laravel 和 VueJs 的页面加载时通过 Web 套接字发出客户端事件?
- powerbi - Power BI 新手在应用切片器后查找结果计数
- ios - 如何在整个应用程序顶部添加一个 UIView 将每个屏幕设计向下推
- r - 绑定数据后无法在 Rstudio 中保存 Excel 文件
- json - 列表中的 Python 字符串元素是 NoneType
- logging - 在 Apache Storm Workers 中设置与 logstash 兼容的日志记录模式
- typescript - TypeScript 可以从另一个通用参数推断出一个通用参数吗?
- amazon-web-services - aws 胶水 HiveContext 访问胶水 DataCatalog
- html - input type=number 用于用户名登录和保存密码
- java - JDK 11 vs JDK 13 performance