threads - what primitive do you use for synchronization purposes in a threaded application




Is LinkedList thread-safe when I'm accessing it with offer and poll exclusively? (5)

I have a linked list samples:

protected LinkedList<RawDataset> samples = new LinkedList<RawDataset>();

I'm appending elements to the list in thread 1 like this:

this.samples.offer(data);

And I'm retrieving elements from it in a second thread like so:

public RawDataset retrieveSample() {
    return this.samples.poll();
}

Would this be considered as thread-safe? Even though thread 1 and 2 are both modifying the list they only do so on either the head or the tail of the list exclusively, right?

If it isn't can anyone point me to a class in the Java API that comes with poll/offer and is sure to be thread-safe?

Thank you in advance.

BTW: Collections.synchronizedList(new LinkedList()) won't give me access to offer/poll.



LinkedList is not thread safe. You'd have to do the locking yourself.

Try ConcurrentLinkedQueue or LinkedBlockingDeque instead if it fits your needs, they are thread safe but slightly different behavior than LinkedList.


if you have a JDK, you can look at the source code of "Collections.synchronizedList()". It is simple, so you can create a copy of this method specialized to get both LinkedList and synchronization functionnalities.

public class SynchronizedLinkedList<T> implements List<T> {

    private LinkedList<T> list;

    private Object lock;

    public void add(T object) {
        synchronized(lock) {
            list.add(object);
        }
    }

    // etc.
}

Is it safe to add items to a linked list while iterating

No, it is not safe. The following code will throw a ConcurrentModificationException:

final LinkedList<Foo> worklist = new LinkedList<>();
worklist.add(new Foo());
Iterator<Foo> iterator = worklist.iterator();
while (iterator.hasNext()) {
    Foo foo = iterator.next();
    worklist.add(new Foo());
}

LinkedList does not override iterator() and the default implementation, defined in AbstractSequentialList is to call listIterator(), and LinkedList does override listIterator.

Quoting the documentation of LinkedList.listIterator:

The list-iterator is fail-fast: if the list is structurally modified at any time after the Iterator is created, in any way except through the list-iterator's own remove or add methods, the list-iterator will throw a ConcurrentModificationException.

What you want is to use explicitely a ListIterator, instead of an Iterator, and use ListIterator.add:

final LinkedList<Foo> worklist = new LinkedList<>();
worklist.add(new Foo());
ListIterator<Foo> iterator = worklist.listIterator();
while (iterator.hasNext()) {
    Foo foo = iterator.next();
    iterator.add(new Foo());
}

The new element is inserted before the element that was returned by next() so subsequent calls to next() are unaffected. If you want to add the new item to the iteration, you can call previous() (and ignore the return value) after adding the element to move the cursor backwards.


java.lang.ClassCastException: Creating a synchronized Linked List

Use Collections.synchronizedList() method instead. The method returns a List<T>. So, make the type on LHS as List, to avoid typecast:

List<A<? extends B>> eopList = Collections.synchronizedList(new LinkedList<A<? extends B>>());