I have a worker thread which should iterate over an ArrayList<ConcurrentLinkedQueue>. Other threads can add and remove objects (queues). But ArrayList is not thread-safe. Would it be fine to use ConcurrentLinkedQueue<ConcurrentLinkedQueue> instead of ArrayList<ConcurrentLinkedQueue>?
If you are asking if you can iterate a ConcurrentLinkedQueue safely, then the answer is Yes. The javadoc says:
Iterators are weakly consistent, returning elements reflecting the state of the queue at some point at or since the creation of the iterator. They do not throw ConcurrentModificationException, and may proceed concurrently with other operations. Elements contained in the queue since the creation of the iterator will be returned exactly once.
However, there are things that you can do on a List that you cannot do on a Queue (e.g. positional get / set, insertion / removal of arbitrary elements.) If your application needs to do those things or similar, then using ConcurrentLinkedQueue instead of ArrayList won't work.
Also, beware that ConcurrentLinkedQueue.size() is an O(N) operation!
Related
Is CopyOnWriteArrayList list enough to use as a collection for shopping-cart. As I understand it is thread-safe and the iterator is guaranteed not to throw ConcurrentModificationException when during iteration another thread removes a product. For example:
...
CopyOnWriteArrayList<Product> products = (CopyOnWriteArrayList<Product>)session.getAttribute("PRODUCTS");
products.addIfAbsent(aProduct);
...
P.S. I found synchronization approaches using synchronized (session) {...} but it seams a little ugly when I need synchronize session access everywhere when I work with shopping-cart as offered in this article
You need to understand what CopyOnWriteArrayList provides.
It provides you a snapshot and does not give you real time view of backend array.
It weakens the contract of visibility, it says that you will not get ConcurrentModificationException but also says that if other thread removes some element, the effect will not be visible to other thread which is iterating maybe, because on addition or removal the original array is not mutated or touched and a new one is created on every operation that mutates the backing array.
Is CopyOnWriteArrayList list enough to use as a collection for
shopping-cart.
Depends.
If this behavior is acceptable in your scenario then you can use it, but if you want visibility guarantee you may have to use explicit locking.
I think you are good to go with CopyOnWriteArrayList in the scenario you described.
It has sufficient guarantees to work as thread safe Implementations including
visibility. Yes it is true that it gives the snapshot of the data when you call iterate.
But there is always a race condition, while you remove it before reading or read it before removing.CopyOnWriteArrayList is a fine implementation
which can be used where reads >>> writes, which i think is the case in shopping cart use case.
It is just that while iterating you will not see changes (write operation). You should understand nothing is free, if you want to see the changes while traversing you need to properly synchronize your every iteration with any write operation which is will compromise perfomance. Trust me you will gain nothing. Most of the concurrent Data structures gives weakly consistent state on iteration see (ConcurrentSkipListSet).
So use either CopyOnWriteArrayList, ConcurrentSkipListSet you are good to go.
I think sets are better for your use case i.e to avoid duplicate orders ..
Is CopyOnWriteArrayList list enough to use as a collection for shopping-cart
No because it depends on what you need to synchronize. Think about what must not happen at the same time.
As I understand it is thread-safe and the iterator is guaranteed not to throw ConcurrentModificationException when during iteration another thread removes a product.
You will not get a ConcurrentModificationException because every modification you do to the list will create a copy of the list. A thread that iterates will use the most current copy. But that thread can't assume that a product is still actually in the list when it sees it. It might have been removed in the most current version.
Or maybe to use "heavier artillery" like following, in all places when accessing to shopping-cart collection.
AtomicReference<List<Product>> productListRef =
AtomicReference<List<Product>>)session.getAttribute("PRODUCTS");
List<Product> oldList;
List<Product> newList;
do {
oldList = productListRef.get();
newList = new ArrayList<>(oldList);
newList.add(aProduct);
} while (!ref.compareAndSet(oldList, newList));
Thank a lot for previous answers!
ArrayList is not synchronized. But there's a way the get a synchronized one as mentioned in java.util.ArrayList's JavaDoc:
List list = Collections.synchronizedList(new ArrayList(...));
In java.util.Collections JavaDoc you can read that "It is imperative that the user manually synchronize on the returned list when iterating over it:"
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Using a synchronized ArrayList results in additional work, why not use a
java.util.Vector instead? Is there an advantage in using this approach?
I found this question on http://www.coderanch.com/ and I'm sharing its great answer here from the same post.
In java.util.Collections JavaDoc you can read that "It is imperative that the user manually synchronize on the returned list when iterating over it:"
If you are doing multiple transactions on a list (like iterating across it), then a synchronized list will not protect you from a ConcurrentModificationException. There is still the possibility that someone will add or remove to the list while you are iterating across it and that will throw.
The Collections.synchronizedList() protects the list against concurrent operations from multiple threads. In the case of the iterator, you are making list calls but then returning to your code and then making list calls again. Even though the methods are synchronized, you are not protected against the race conditions of other threads operating on the list in the meantime.
Using a synchronized ArrayList results in additional work, why not use a java.util.Vector instead? Is there an advantage in using this approach?
Vector is not going to help here. It will also throw an exception under the same circumstance. To quote from the javadocs:
The Iterators returned by Vector's iterator and listIterator methods are fail-fast: if the Vector is structurally modified at any time after the Iterator is created, in any way except through the Iterator's own remove or add methods, the Iterator will throw a ConcurrentModificationException.
Also, Vector is a very old class. It is widely held that it is better to use a synchronized ArrayList.
Here's a couple of things that you can do:
You can copy the list into another collection which you then can iterate across. Even if other threads add or delete from the synchronized list, your local collection is safe. This doesn't protect you from modifications to the elements of the list of course.
You could switch to a fully concurrent collection such as ConcurrentHashMap (it's not a list of course), that handles modifications to the collection while you are iterating. ConcurrentSkipList or LinkedBlockingQueue are other choices.
As #Geek points out, CopyOnWriteArrayList is another option although the performance depends a lot on the ratio to iterating and writing.
I am iterating through a Hashtable and at one point, I add something in to the Hashtable which is clearly giving me a ConcurrentModificationException. I understand why I am getting the error, but is there a way around this such that I could still iterate through the Hashtable and add values simultaneously?
From the docs
The iterators returned by the iterator
method of the collections returned by
all of this class's "collection view
methods" are fail-fast: if the
Hashtable is structurally modified at
any time after the iterator is
created, in any way except through the
iterator's own remove method, the
iterator will throw a
ConcurrentModificationException. Thus,
in the face of concurrent
modification, the iterator fails
quickly and cleanly, rather than
risking arbitrary, non-deterministic
behavior at an undetermined time in
the future. The Enumerations returned
by Hashtable's keys and elements
methods are not fail-fast.
Note that the fail-fast behavior of an
iterator cannot be guaranteed as it
is, generally speaking, impossible to
make any hard guarantees in the
presence of unsynchronized concurrent
modification. Fail-fast iterators
throw ConcurrentModificationException
on a best-effort basis. Therefore, it
would be wrong to write a program that
depended on this exception for its
correctness: the fail-fast behavior of
iterators should be used only to
detect bugs.
If you need this kind of behavior you can safely copy the set of keys and iterate through the copy. Another option if the hashtable is large and copying the keyset is likely to be expensive is to add to a separate collection during the iteration and add the elements of the separate collection post iteration.
You may also want to know about CopyOnWriteSet, which is specifically designed for safe iteration while set is modified. Note that iterator sees only the original set. Any additions will not be visible until next iteration.
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CopyOnWriteArraySet.html
This is most useful in many readers / few writers scenario. It is unlikely to be the most efficient solution if reading and writing happens in the same code path.
Make a new Hashtable that you add new entries to; then when you are done iterating, add in the entries from the first table.
Optionally, if you need to, you can skip keys that exist in the original table.
Another alternative would be to use a ConcurrentHashMap instead of a HashMap. However:
The iterators for a ConcurrentHashMap are defined to return objects reflecting a state some time at or after the creation of the iterator. A more precise statement of the behaviour is in the javadocs for the relevant methods.
A ConcurrentHashMap is probably slower than a regular HashMap.
my code throw follow exception:
java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
at java.util.LinkedList$ListItr.next(LinkedList.java:696)
at java.util.AbstractCollection.addAll(AbstractCollection.java:305)
at java.util.LinkedHashSet.<init>(LinkedHashSet.java:152)
...
I want a ConcurrentLinkedHashSet to fix it,
but I only found ConcurrentSkipListSet in java.util.concurrent,this is TreeSet, not LinkedHashSet
any easies way to get ConcurrentLinkedHashSet in JDK6.0?
thanks for help :)
A ConcurrentModificationException has nothing to do with concurrency in the form you're thinking of. This just means that while iterating over the Collection, someone (probably your own code - that happens often enough ;) ) is changing it, i.e. adding/removing some values.
Make sure you're using the Iterator to remove values from the collection and not the collection itself.
Edit: If really another thread is accessing the Collection at the same time, the weak synchronization you get from the standard library is useless anyhow, since you've got to block the Collection for the whole duration of the operation not just for one add/remove! I.e. something like
synchronize(collection) {
// do stuff here
}
You can always create a synchronized collection with Collections.synchronizedMap(myMap);. However, trying to alter the map while you're iterating (which I'm assuming is the cause of your error) will still be a problem.
From the docs for synchronizedMap:
Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee serial access, it is critical that all access to the backing map is accomplished through the returned map.
It is imperative that the user
manually synchronize on the returned
map when iterating over any of its
collection views ... Failure to follow
this advice may result in
non-deterministic behavior.
This is because
normally a concurrent collection is really guaranteeing atomic get/put but is not locking the entire collection during iteration, which would be too slow. There's no concurrency guarantee over iteration, which is actually many operations against the map.
it's not really concurrency if you're altering during iteration, as it's impossible to determine correct behavior - for example, how do you reconcile your iterator returning hasNext == true with deleting a (possibly the next value) from the collection?
There is ConcurrentLinkedHashMap - https://code.google.com/p/concurrentlinkedhashmap/
You can create Set out of it with java.util.Collections.newSetFromMap(map)
Unfortunately not. You could implement your own, wrapping a ConcurrentHashMap and a ConcurrentLinkedQueue, but this wouldn't allow you to remove values easily (removal would be O(N), since you'd have to iterate through everything in the queue) ...
What are you using the LinkedHashSet for though? Might be able to suggest alternatives...
When do we use synchronized ArrayList? We already have Vector which is synchronized.
I think that you've got this wrong. ArrayList is unsynchronized, Vector is.
Being synchronized means that every operation is thread safe - if you use the same vector from two threads at the same time, they can't corrupt the state. However, this makes it slower.
If you are working in a single threaded environment (or the list is limited to a thread and never shared), use ArrayList. If you are working with multiple threads that share the same collection, either use Vector, or use ArrayList but synchronize in some other way (e.g., manually or via a wrapper).
ArrayList is not synchronized via http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html
ArrayList is not synchronized out of the box.
Resizable-array implementation of the
List interface. Implements all
optional list operations, and permits
all elements, including null. In
addition to implementing the List
interface, this class provides methods
to manipulate the size of the array
that is used internally to store the
list. (This class is roughly
equivalent to Vector, except that it
is unsynchronized.)
This avoids some performance issues in situations where you know that you won't need thread safety (e.g., entirely encapsulated private data). However both ArrayList and Vector have issues when using iterators over them: when iterating through either type of collection, if data is added or removed, you will throw a ConcurrentModificationException:
Note that this implementation is not
synchronized. If multiple threads
access an ArrayList instance
concurrently, and at least one of the
threads modifies the list
structurally, it must be synchronized
externally. (A structural modification
is any operation that adds or deletes
one or more elements, or explicitly
resizes the backing array; merely
setting the value of an element is not
a structural modification.) This is
typically accomplished by
synchronizing on some object that
naturally encapsulates the list. If no
such object exists, the list should be
"wrapped" using the
Collections.synchronizedList method.
This is best done at creation time, to
prevent accidental unsynchronized
access to the list:
List list =
Collections.synchronizedList(new
ArrayList(...));
The iterators returned by this class's
iterator and listIterator methods are
fail-fast: if the list is structurally
modified at any time after the
iterator is created, in any way except
through the iterator's own remove or
add methods, the iterator will throw a
ConcurrentModificationException. Thus,
in the face of concurrent
modification, the iterator fails
quickly and cleanly, rather than
risking arbitrary, non-deterministic
behavior at an undetermined time in
the future.
Note that the fail-fast behavior of an
iterator cannot be guaranteed as it
is, generally speaking, impossible to
make any hard guarantees in the
presence of unsynchronized concurrent
modification. Fail-fast iterators
throw ConcurrentModificationException
on a best-effort basis. Therefore, it
would be wrong to write a program that
depended on this exception for its
correctness: the fail-fast behavior of
iterators should be used only to
detect bugs.
ArrayList comes in a variety of useful flavors, however, while Vector does not. My personal favorite is the CopyOnWriteArrayList:
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created. Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.
CopyOnWriteArrayLists are tremendously useful in GUI work, especially in situations where you are displaying an updating set of data (e.g., moving icons on a screen). If you can tolerate having your displayed list of data be one frame out of date (because your producer thread is slightly behind your graphical update thread), CopyOnWriteArrayLists are the perfect data structure.
What does it mean array list is synchronized in java?
It means it is thread-safe.
Vectors are synchronized. Any method that touches the Vector's contents is thread safe.
ArrayList, on the other hand, is unsynchronized, making them, therefore, not thread safe.
I read ArrayList is synchronized in
java..
But the array list api says that
Note that this implementation is not
synchronized
So you use an ArrayList when you are sure that you wont be dealing with concurrency.
Using Vector might be an overkill, and may result in performance issues.