Do I have to synchronize on a List that is read by a stream?

AnnaKlein :

if I have a Thread sensitive List I go usually like this while iterating over it:

    List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());   
}

I wonder if I use list.stream() and do then some operations over the stream like filter etc., if I also have to put the list into a synchronize block or does the stream makes a copy of the list?

Thanks

Roman Puchkovskiy :

Stream operations use spliterator() method internally.

Here is the spliterator() method from ArrayList:

    public Spliterator<E> spliterator() {
        checkForComodification();
        return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                           offset + this.size, this.modCount);
    }

It checks for comodification, so it looks like stream() operations have to be inside synchronized blocks in your case.

Also, spliterator() of SynchronizedCollection (in Collections) has comment

    public Spliterator<E> spliterator() {
        return c.spliterator(); // Must be manually synched by user!
    }

which is analogous to the comment in iterator():

    public Iterator<E> iterator() {
        return c.iterator(); // Must be manually synched by user!
    }

which shows the same: synchronization is needed around stream() operations (at least, if iterator() requires such a synchronization).

And the most convincing: stream() method from SynchronizedCollection:

    public Stream<E> stream() {
        return c.stream(); // Must be manually synched by user!
    }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=445168&siteId=1