everyone. To Test a ArrayList returned by the Collections.synchronizedList() method, I defined a static class as below.
static class ListWriter implements Runnable {
private List<Integer> list;
public ListWriter(List<Integer> list) {
this.list = list;
}
public void run() { // I didn't use synchronized(list) {} block here.
try {
for (int i = 0; i < 20; i++) {
list.add(i);
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
and a test method as below
private static void test1() throws Exception {
List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
Thread t1 = new Thread(new ListWriter(list));
Thread t2 = new Thread(new ListWriter(list));
t1.start();
t2.start();
t1.join();
t2.join();
for (int i = 0; i < list.size(); ++i) {
System.out.println(list.get(i));
}
}
The result is usually this:
0
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
But sometimes it will be like this:
0
0
1
1
2
3
2
3
4
5
4
5
6
7
6
8
7
9
8
10
9
11
10
12
11
13
12
14
13
15
14
15
16
17
16
17
18
19
18
19
Does these results indicates the process is thread-safe?
The point is that I didn’t use a synchronized block in the writing thread which is explicitly required for iterating over the synchronized ArrayList returned by Collection.synchronizedList() method. So do you think the process is thread-safe or do I need to use synchronized block anyway?
The output is non-deterministic – it depends on the scheduling behaviour of the underlying operating system.
The fact that sometime you get a certain sequence is just a coincidence.
Your list is synchronised at creation by the
Collections.synchronizedListso you don’t need any additional synchronisation.A rough test of the thread-safeness of your list would be to validate that the number of elements contained in the list equals 40 after both threads are done.
As you noted, for concurrent reading you will need to synchronize on the returned list as stated in the documentation