import java.util.ArrayList;
import java.util.List;
public class unsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 101; i++) {
int finalI = i;
new Thread(() -> {
synchronized (list) {
list.add(Integer.toString(finalI));
}
}).start();
}
// Thread.sleep(100);
System.out.println(list.size());
String string = list.stream()
.map(Integer::valueOf)
.reduce(0, Integer::sum)
.toString();
System.out.println(string);
}
}
output:
93
5050
output2:
101
5050
I put a synchronization lock on the list to ensure that the ArrayList can add information safely, but the numbers I printed out were not as many as I imagined, and then I performed the accumulation operation and found that the obtained value was the correct result.
if I change list.size
to list.stream.count()
method ,that's right result, How should I understand it?
There are two problems here:
You start the threads, but you don't wait for them to finish, using Thread.join()
You don't synchronize access to the list from the main thread, with the size()
and stream()
calls.
Note that the Javadoc for ArrayList
says:
If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
It's perhaps easy to forget that the main thread is a thread like any other, and so you need synchronization there too.