When running the following code:
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
public final class ThreadTest {
int N = 4;
Map<Integer, Proxy> proxy = Collections.synchronizedMap(new TreeMap<>());
Proxy p;
public static void main(String[] args) {
new ThreadTest();
}
public ThreadTest() {
Thread[] t = new Thread[N];
for(int c=0;c<N;c++) {
final int i = c;
t[i] = new Thread(() -> {
try {
System.out.println( "From thread: " + i );
p = new Proxy(i);
proxy.put(i, p);
p.init();
} catch (Exception e){}
});
t[i].start();
}
for(int c=0;c<N;c++) {
try {
t[c].join();
} catch (InterruptedException e){}
}
}
public class Proxy {
int index;
public Proxy(int index) {
this.index = index;
System.out.println( "Proxy: " + index );
}
public void init() {
System.out.println("Initializing " + index );
}
}
}
the printed indices from the method init()
are not unique. The following is an example output:
From thread: 0
From thread: 1
From thread: 2
From thread: 3
Proxy: 0
Proxy: 3
Proxy: 2
Proxy: 1
Initializing 3
Initializing 3
Initializing 1
Initializing 2
Although I have synchronized the TreeMap
with Collections.synchronizedMap()
, the result is the same for an unsynchronized Map
. This behavior seems quite odd considering it is just a put method and the index has changed completely. Could anybody please explain what is happening? Thanks.
Your problem is that your p
variable is shared by all threads.
From the prints in init
, it shows that this code block that the p
variable is written over by another thread before init
is called
p = new Proxy(i);
proxy.put(key, p);
p.init();