Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Java ArrayList / String / atomic variable reading thread safe?

I've been mulling this over & reading but can find an absolute authoritative answer.

I have several deep data structures made up of objects containing ArrayLists, Strings & primitive values. I can guarantee that the data in these structures will not change (no thread will ever make structural changes to lists, change references, change primitives).

I'm wondering if reading data in these structures is thread safe; i.e. is it safe to recursively read variables from the objects, iterate the ArrayLists etc. to extract information from the structures in multiple threads without synchronization?

like image 370
Jon M Avatar asked Mar 05 '10 17:03

Jon M


People also ask

Is ArrayList Add thread-safe?

The standard ArrayList is not thread-safe and the behavior when multiple threads update at the same time is undefined. There can also be odd behaviors with multiple readers when one or more threads is writing at the same time.

Is reading from a list thread-safe Java?

The collection interfaces in Java – List , Set , Map – have basic implementations that are not threadsafe. The implementations of these that you've been used to using, namely ArrayList , HashMap , and HashSet , cannot be used safely from more than one thread.

Which variables are thread-safe in Java?

Local variables are thread safe in Java.

How do you make an ArrayList thread-safe in Java?

A thread-safe variant of ArrayList in which all mutative operations (e.g., add, set, remove..) are implemented by creating a separate copy of an underlying array. It achieves thread safety by creating a separate copy of the List which is different than vector or other collections used to provide thread-safety.


2 Answers

The only reason why it wouldn't be safe is if one thread were writing to a field while another thread was simultaneously reading from it. No race condition exists if the data is not changing. Making objects immutable is one way of guaranteeing that they are thread safe. Start by reading this article from IBM.

like image 191
Amir Afghani Avatar answered Oct 22 '22 08:10

Amir Afghani


The members of an ArrayList aren't protected by any memory barriers, so there is no guarantee that changes to them are visible between threads. This applies even when the only "change" that is ever made to the list is its construction.

Any data that is shared between thread needs a "memory barrier" to ensure its visibility. There are several ways to accomplish this.

First, any member that is declared final and initialized in a constructor is visible to any thread after the constructor completes.

Changes to any member that is declared volatile are visible to all threads. In effect, the write is "flushed" from any cache to main memory, where it can be seen by any thread that accesses main memory.

Now it gets a bit trickier. Any writes made by a thread before that thread writes to a volatile variable are also flushed. Likewise, when a thread reads a volatile variable, its cache is cleared, and subsequent reads may repopulate it from main memory.

Finally, a synchronized block is like a volatile read and write, with the added quality of atomicity. When the monitor is acquired, the thread's read cache is cleared. When the monitor is released, all writes are flushed to main memory.

One way to make this work is to have the thread that is populating your shared data structure assign the result to a volatile variable (or an AtomicReference, or other suitable java.util.concurrent object). When other threads access that variable, not only are they guaranteed to get the most recent value for that variable, but also any changes made to the data structure by the thread before it assigned the value to the variable.

like image 5
erickson Avatar answered Oct 22 '22 08:10

erickson