【发布时间】:2014-04-03 16:18:46
【问题描述】:
我的应用程序设计如下:
- 数据不断地附加到 ArrayList(通过多次写入)
- 读取器线程从列表的开头读取数据(保证在受当前写入影响的索引之前)。
是否有线程安全的方式来实现它,以便:
写入器线程在写入时相互阻塞(以避免写入并发问题)
当其他读者阅读时,读者线程不会被阻塞
-
读取器线程不会被阻塞当写入器线程追加到末尾时
我在这里做一个假设,对于数组开头的读取器来说,仅仅写入 ArrayList 的末尾是线程安全的
-
但是,当写入某些操作会使读取线程不安全时,读取线程会被阻塞 - 如果数组在追加期间用完分配的内存,则会重新分配整个数组数据。
我在这里假设重新分配 ArrayList 的内存对于数组开头的读取器不是线程安全的 - 如果数组增长实际上是通过在末尾添加更多链接数组而不更改原始数组来实现的这可能是一个错误的假设。
更新:最终我没有解决这个令人头疼的问题,而是简单地将整个系统重新设计为数组。这样,我只能在创建 - 或者更确切地说,添加 - 新子数组时锁定父数组;并且任何其他锁都在单独的子数组上,无论如何都会被程序中的所有操作原子处理,因此不会受到锁定问题的影响。
【问题讨论】:
-
注意:CopyOnWriteArrayList 对我不起作用,因为插入与读取相当,因此每次写入时复制都会非常昂贵
-
您是否尝试过简单地使用 ReadWriteLock 并进行测量?也许它已经足够快了。
-
看看 Disruptor 库 lmax-exchange.github.io/disruptor 可能是值得的,它为 java 提供了一个循环缓冲区实现,避免在大多数/所有情况下锁定。
标签: java arraylist concurrency thread-safety