javasynchronized

java synchronized how can i understand it


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?


Solution

  • There are two problems here:

    1. You start the threads, but you don't wait for them to finish, using Thread.join()

    2. 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.