I have an array which contains integer values declared like this:
int data[] = new int[n];
Each value needs to be processed and I am splitting the work into pieces so that it can be processed by separate threads. The array will not be modified during processing.
Can all the processing threads read separate parts of the array concurrently? Or do I have to use a lock?
In other words: is this work order thread-safe?
Array is created and filled
Threads are created and started
Thread 0 reads data[0..3]
Thread 1 reads data[4..7]
Thread 2 reads data[8..n]
Reading contents of an array (or any other collection, fields of an object, etc.) by multiple threads is thread-safe provided that the data is not modified in the meantime.
If you fill the array with data to process and pass it to different threads for reading, then the data will be properly read and no data race will be possible.
Note that this will only work if you create the threads after you have filled the array. If you pass the array for processing to some already existing threads without synchronization, the contents of the array may not be read correctly. In such case the method in which the thread obtains the reference to the array should be synchronized, because a synchronized block forces memory update between threads.
On a side note: using an immutable collection may be a good idea. That way you ensure no modification is even possible. I would sugges using such wrapper. Check the java.util.concurrent.atomic package, there should be something you can use.
As long as the threads don't modify the contents in the array, it is fine to read the array from multiple threads.
If you ensure all the threads are just reading, its thread safe. Though you should not be relying on that fact alone and try to make your array immutable via a wrapper.
Sure, if you just want to read it, pass the array to the threads when you create them. There won't be any problem as long as you don't modify it.
Reading from array array is Thread-Safe Operation but if you are Modifying array than consider using class AtomicIntegerArray.
Consider populating a ConcurrendLinkedQueue and have each thread pull from it. This would ensure that there are no concurrency issues.
Your threads would each be pulling their data from the top of the queue and processing it.
Related
Two questions I want to ask with regards to java:
Given an array of objects, ObjectClass array[25] that's been initialized, would it be thread safe to pass such an array to multiple threads and have them use it only as a reference for information? None of the threads will change the contents of the array, just read from it.
Same question, but instead of an array, we have a map. I heard that modifying a map is not thread safe but simply reading from it is?
Thanks
Reading contents of an array by multiple threads is thread-safe only
if data isn't modified i.e. if you create the threads after you have
filled the array However if you pass the initialized array to
existing thread without synchronizing the data may be read out of
sync.
You may consider using java.util.concurrent.ConcurrentHashMap
for #2 instead.
My application is designed the following way:
Data is continuously appended to an ArrayList (by multiple writes)
Data is read from the beginning of the list (guaranteed to be before the indexes affected by the current writes) by reader threads.
Is there a thread safe way to implement it so that:
Writer threads are blocking each other when writing (to avoid write concurrency issues)
Reader threads aren't blocked when either other readers read
Reader threads aren't blocked when writer threads append to the end
I am making an assumption here that merely writing to the end of ArrayList is thread safe for the reader of the array's start
However, read threads are blocked when writing cases some operation that would make reading thread unsafe - such reallocating full array data if the array runs out of allocated memory during an append.
I am making an assumption here that reallocating the memory of ArrayList is NOT thread safe for the reader of the array's start - if the array growth is actually implemented by adding more linked arrays to the end without changing the original array that may be a false assumption.
UPDATE: Rather than deal with this headache, in the end, I simply re-designed the whole system to be an array of arrays. This way I can lock the parent array ONLY when creating - or rather, adding - the new sub-array; and any other locks are on individual sub-arrays that are treated atomically by all operations in the program anyway and thus won't suffer from locking issues.
How can I achieve the safe read/write concurrency on an ArrayList?
It's hard to figure out what is actually happening to the list. Items are being added to the end of the while readers are consuming from the front but I can't tell if multiple readers read a single item or does every reader consume every element?
But regardless, I would consider switching to using a BlockingQueue like an ArrayBlockingQueue. ArrayList is not at all built for your use case. I would have a BlockingQueue for the work and then another BlockingQueue for the results. Again, this assumes that entries in your list are not consumed by multiple threads.
One of the main issues here is that synchronization performances two functions: mutex protection and memory synchronization. The writers have to lock so they don't collide but the readers need to lock to be able to see the writers' updates to the list.
In terms of the blocking specifics, some of your requirements are not possible because of the race conditions involved with dynamically extending the list.
I am making an assumption here that merely writing to the end of ArrayList is thread safe for the reader of the array's start
This is true unless the write to the end of the list causes the list to be reallocated. However, again, you need to synchronize on the list to see any of the updates made to the list by the writers. Even if your ArrayList is volatile the fields inside of the list are not.
I am making an assumption here that reallocating the memory of ArrayList is NOT thread safe for the reader of the array's start...
No it is not. No part of the ArrayList is thread safe when it comes to the array of data. I'd recommend looking at the source if there is any question. The following method is called from add(...) and any other method that changes the size of the list.
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
I'm unsure why you are using an ArrayList at all. What you are describing is a queue, a First-In-First-Out data structure. Java offers several Queue implementations that are thread-safe, notably ConcurrentLinkedQueue and LinkedBlockingQueue.
An ArrayList is fundamentally not thread-safe, and the only way to make it so is by wrapping it in a call to Collections.synchronizedList() which will make read and write access to the array essentially single-threaded.
Consider scenario:
Reader R1 takes the list and works with it
Writer W1 appends an element to the list, without array reallocation
Reader R2 takes the list and works with it.
The question is: should the list objects seen by R1 and R2 be different, or can be the same? In the first case, each write operation has to create new object, though underlying array can be the same (which is much more efficient than using CopyOnWriteArrayList). In the second case, R1 can see that the length of the list can grow unpredictably, which may cause programming errors.
In both cases, AtomicReference can be used to store current version of the list. Readers simply get the current list from it, and writers use additional object with monitor to synchronize update operations.
I have a simple ArrayList and I am feeding this ArrayList from multiple Threads via Java concurrency. Each Thread will only read the same instance of this ArrayList. Is there any chance of error during the reading operation?
Provided there are no more writes make it immutable using Collections.unmodifiableList and then forget about read issues.
If the list is fully populated and always accessed in read-only by all the threads, you won't have a problem. If there is a write operation, then you need to synchronize all the accesses to the list, or to use a concurrent list (like CopyOnWriteArrayList).
In my application I have two threads. Thread 1 is transferring data to Thread 2. After the data is transferred the data in thread 1 is cleared within thread 2. Thread 1 goes on its merry way placing more data in the HashMap as it comes in to be transferred to Thread 2 later. In the meantime, Thread 2 does what it needs to do with the data. The code I have below is the part in thread 2 where that data transfer between threads happens. The entire application works just fine, but my questions is, is there a better way to make this copy of the thread 1 data for thread 2 without using the keyword new to create a whole new object?
I figure doing this might cause more garbage collections to occur? Should I not worry about this?
synchronized(this){
// Make a copy of the data map then clear it.
cachedData = new HashMap<String,ArrayList<Float>>(data);
data.clear();
}
So if you are accessing this data HashMap from multiple threads then you will have to have a synchronized block on every access. Just because you are grabbing a cached copy here does not mean that other threads get to use the data without synchronization.
If you want to have concurrent usage of HashMap without having to synchronize around each usage then you should be using a ConcurrentHashMap.
The entire application works just fine, but my questions is, is there a better way to make this copy of the thread 1 data for thread 2 without using the keyword new to create a whole new object?
Taking into account the cautions I mentioned above, if you want to take a snapshot of a HashMap so you can work with the contents in a specific thread then the pattern you mention is fine and is often used. This pattern is also used when you need to iterate through a Collection and modify it inside of the loop but without doing an iterator.remove().
If you just need the keys or the values then make sure to take a copy of the data.keySet() or data.values() instead.
Why not just:
synchronized(this){
cachedData = data;
data = new HashMap<String,ArrayList<Float>>();
}
This is similar to what you have, but involves no copying of the data.
I wouldn't worry about the new too much (not unless you can prove through profiling that it's a problem).
I have a kind of async task managing class, which has an array like this:
public static int[][][] tasks;
Mostly I access the cells like this:
synchronized(tasks[A][B]) {
// Doing something with tasks[A][B][0]
}
My question is, if I do this:
synchronized(tasks[A]) {
// ...
}
will it also block threads trying to enter synchronized(tasks[A][B])?
In other words, does a synchronized access to an array also synchronizes the accsess to it's cells?
If not, how to I block the WHOLE array of tasks[A] for my thread?
Edit: the answer is NO. When someone is in a synchronized block on tasks[A] someone else can simultaniously be in a synchronized block on tasks[A][B] for example - because it's a different object. So when talking about accessing objects from one place at a time, arrays are no different: to touch object X from one place at a time you need to surround it by synchronized(X) EVERYWHERE you touch it.
No. Each array is an Object (with a monitor) unto itself; and the array tasks[A] is a distinct object from the array tasks[A][B]. The solution, if you want to synchronize all accesses to "sub" arrays of tasks[A] is simply that you must do synchronized (tasks[A]). If all accesses into the descendant objects (say, tasks[A][B]) do this, then any further synchronization is redundant.'
It appears your underlying question is actually something like "how can I safely modify the structure as well as the contents of a data structure while retaining the best concurrency possible?" If you augment your question a bit more about the problem space, we might be able to delve deeper. A three-dimensional array may not be the best solution.
int[][][] is an array of arrays of integer arrays, so your synchronized(tasks[A][B]) is synchronizing on the lowest level object, an array of integers, blocking other synchronized access to that same array.
synchronized(tasks[A]) on the other hand is synchronizing the object at the next level up - an array of integer arrays. This prevents synchronized access to that array, which means, in practice that any other code which uses synchronized(tasks[A]) will be blocked - which seems to be what you want, so long as all your acccesses to tasks synchronizes at the same level.
Note that synchronize does not lock anything! However, if two threads attempt to synchronize on the same object, one will have to wait.
It doesn't matter that you then work on another object (your array of integers).
I'm afraid I'm saying that andersoj's answer is misleading. You're doing the right thing.
Whenever I see code that grabs lots of different mutexes or monitors, my first reaction is to worry about deadlock; in your current code, do you ever lock multiple monitors in the same thread? If so, do you ensure that they are locked in a canonical ordering each time?
It would probably help if you could explain what you are trying to accomplish and how your are using / modifying this tasks array. There are surprising (or perhaps unsurprising) number of cases where the utilities in java.util.concurrent are sufficient, and using individual monitors isn't necessary. Of course, it all depends on what exactlly you are trying to do. Also, if the reason you are trying to grab so many different locks is because you are reading them very frequently, it is possible that using a single read-write lock for the entire 3d jagged-array object might be sufficient for your needs.