Is it possible that an ArrayList will fail with a single recorder system?

I have a List that should be called by multiple threads. There will be only one writer, and this writer will add elements and do nothing. Items are never deleted or changed. Many concurrent read streams will call list.size() and list.get(index) .

We must assume that sometimes the internal array will have to grow as elements are added.

Can I get away using a simple ArrayList , or do I need to implement some fancy parallel structure to avoid exceptions?

+5
source share
4 answers

If your readers all need to read the same List state, which means the writer cannot write between all readers, then yes, you will need to use ReadWriteLock or a more sophisticated method to handle this case.

If you're not rid of memory usage, don't mind if your readers always have the latest data available, and your only goal is to simply avoid exceptions, consider CopyOnWriteArrayList , which is built to avoid exceptions in write / iteration conflicts. When you write to this List , it makes a new one as the end result, but readers who currently use the List continue to read “old” (pre-write) instead.

+3
source

So, first, the documentation for ArrayList says that it is not thread safe, so I would not recommend using it in such a case. Moreover, even if it worked theoretically, you would have the problem of ensuring that someone who supports this program remembers the strict restrictions that you imposed on reading and writing with fun if they did not! However, your question is really interesting from a theoretical point of view, so I thought I'd take a look.

The first thing to note is that any of the readers tried to access the list through an iterator, and sooner or later the reading will fail with a ConcurrentModificationException. This is because every modification of the list is tracked, and the Iterator does not work quickly if it detects the modification outside the iterator.

However, you do not indicate the need for using iterators in the original question, and what happens if you restrict yourself to just adding and reading with get () and size ()? In this case, I still think that you can see a random failure, because inside the list stores the current size along with the backup data array, and not a single variable is marked as mutable. As a result (and because of the guarantees of Java memory), I think it is theoretically possible for an updated size variable to appear in one of the reader threads, while the data is still not updated. In this case, you can return the returned spam data or even indexOutOfBounds.

+1
source

If you are open to using a third-party library, Eclipse Collections is of type MultiReaderFastList , which supports multiple readers and one writer. He attacks the iterator . If you need to do an iteration, try using one of the many internal iteration methods that will safely get a read lock and release it after the iteration has completed. If you need to write imperative iterative code, there are two methods called withReadLockAndDelegate and withWriteLockAndDelegate that will allow you to safely block the iterator before and after the code block.

Note. I am the committer for the Eclipse Collection .

+1
source

My suggestion is to use semaphores to avoid any exceptions, so you can control which reader is reading the list at any time.

-1
source

Source: https://habr.com/ru/post/1261599/


All Articles