List setting null values with the parallel stream

fastcodejava :

I have the following code

final String arr[] = {"A", "B", "C", "D"};
final List<String> list1 = new ArrayList<>();
final List<String> list2 = Arrays.asList(arr).parallelStream()
                          .peek(s -> list1.add(s + s))
                          .map(s -> s + s)
                          .collect(Collectors.toList());
System.out.println(list1);
System.out.println(list2);

And I get this following result:

[null, AA, DD, null]
[AA, BB, CC, DD]

Why some of the elements are showing null in list1? I know I'm supposed to use SynchronizedList with parallelStream, but null values are surprising to me. As soon as you add something to a list that slot should be set and next execution should have added another value to it.

Eugene :

ArrayList is not a thread-safe collection, and you try to update it from numerous threads with parallelStream, what you see is the result of resizing the internal array of that ArrayList - that operation is not thread safe either, you first increase the array and then move elements to it : may be elements have not been moved and you try to access it.

To make it more explicit, when resizing happens a new array is created with an increased size - this new array if full of nulls only after the copying happens.

It's really un-predictable what will happen, just don't rely on any of these.

EDIT

I can't post this as a comment, but here is some code proving that null can be seen:

List<Integer> result = IntStream.iterate(0, i -> i + 1)
            .takeWhile(i -> {
                String arr[] = { "A", "B", "C", "D", "E", "F", "G", "H", "R", "T" };
                List<String> list = new ArrayList<>();
                Arrays.stream(arr)
                        .parallel()
                        .peek(list::add)
                        .forEach(x -> {
                        });

                if (list.contains(null)) {
                    System.out.println("It took " + i + " steps to see a null");
                    return false;
                }

                return true;
            })
            .boxed()
            .collect(Collectors.toList());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=114940&siteId=1