【发布时间】:2018-03-08 07:07:12
【问题描述】:
我想写一个简单的线程安全数组列表,它支持:
add()、remove(int i)、insert(int i)、update(int i) 和 get(int i)
一个简单的实现是给内部数据结构(例如一个对象数组)加锁,但这还不够好,因为一次只有一个线程可以访问列表。
因此我最初的计划是为每个数据槽添加锁,以便不同的线程可以同时访问不同索引中的元素。数据结构如下所示:
class MyArrayList {
Lock listlock;
Lock[] locks;
Object[] array;
}
如果不需要resize(),锁定应该如下工作:
- 对于get(int i),线程需要获取锁[i]。
- 对于insert(int i),线程需要获取j >= i 和listlock 的所有锁[j]。
- 对于 remove(int i),线程需要获取所有锁 [j] for j >= i 和 listlock。
- 对于add(),线程需要获取listlock。
- 对于insert(),线程需要获取锁[i]。
我的问题是:
- 在添加更多对象的同时调整大小时如何处理锁,我需要创建一个新的更大的数组来保存所有对象。这很烦人,因为其他一些线程也可能在等待锁被释放,
- 有没有更好的建议来实现这种线程安全的数组列表?
【问题讨论】:
-
List list = Collections.synchronizedList(new ArrayList());呢? -
那个存在,就叫Vector。
-
我认为这是一个练习,而不是一个简单的练习,因为 JDK 中有内置的并发集合。
-
@DwB 感谢您提供的信息。其实我从Vector或者synchronizedList的源码中发现,synchronized关键字是用来保证线程安全的。以 get() 为例,线程 A 想要调用 get(0),而线程 B 想要调用 get(1),使用 synchronized 将只允许一个线程调用 get() 函数,即使两个线程正在尝试读取数据不同的位置。如果线程正在访问不同的插槽,我想做的是同时执行此操作。
-
这绝不是合理的。您不能合理地限制列表上的同步规模,因为有多种方法可以访问列表中的给定元素(迭代器、枚举器、按索引访问),并且将列表增加一个元素可能会导致完全重建数组(即分配新数组,复制旧元素,转储旧数组)。
标签: java multithreading arraylist concurrency synchronization