我想写一个简单的线程安全arraylist,它支持:
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].
> for remove(int i),一个线程需要获取j> = i和listlock的所有锁[j].
>对于add(),线程需要获取listlock.
>对于insert(),线程需要获取锁[i].
我的问题是:
>在更多对象添加时调整大小时如何处理锁定,我需要创建一个新的更大的数组来保存所有对象.这很烦人,因为其他一些线程也可能会等待释放锁,
>有什么更好的建议来实现这种线程安全的arraylist?
解决方法:
一个简单的方法就是使用read-write lock([Reentrant] ReadWriteLock),这么多线程可以同时读取,但是一旦有人获得写锁定,其他人就无法访问该列表.
或者你可以做一些与你的想法有些类似的事情:每个插槽的一个读写锁定全局(“结构”)读写锁定变量以跟踪j> = i情况.所以:
>要访问(读取或写入)任何内容,线程至少需要全局读锁定.
>只有尝试进行结构更改的线程(更改大小的线程)才会获得全局写锁定,但只能设置一个int modifyFrom变量,表示从那里开始的所有位置都被“锁定”(j> = i情况).设置modifyFrom后,您将从写入降级到读锁定(请参阅docs),让其他人访问列表.
>任何线程尝试执行任何非结构更改的线程,一旦持有全局读锁定,检查它想要执行的操作是否与modifyFrom的当前值冲突.如果存在冲突,请一直睡觉,直到设置了modifyFrom的线程完成并通知所有正在等待的人.这个检查必须是同步的(只是在某个对象上使用synchronized(obj))所以在冲突的线程调用obj.wait()并永远休眠(保持全局读取)之前,结构更改线程不会发生在obj.notify()中锁!).