问题
The following code is supposed to prevent Data Racing by using the synchronized method on common. But for some reason the output is always 19915-19980. Shouldn't it be 20000 if it was not data racing?
public class SyncVarDataRace extends Thread {
private static int common = 0;
public void run(){
synchronized((Integer)common){
int local = common;
local+=1;
common = local;
}
}
public static void main(String[] args) throws InterruptedException {
SyncVarDataRace[] allThreads = new SyncVarDataRace[20000];
for(int i = 0; i < allThreads.length; i++){
allThreads[i] = new SyncVarDataRace();
}
for(SyncVarDataRace d: allThreads){
d.start();
}
for(SyncVarDataRace d: allThreads){
d.join();
}
System.out.println(common);
}
}
回答1:
You are trying to synchronize on an auto-boxed object that will be a different object every time.
synchronized((Integer)common){
The whole point is to synchronize on the same object in each thread. Even if you made common be an Integer, as soon as you assign it to another value, it would be a different object.
You need to lock on a constant object instead. I would recommend defining a local Object that you can synchronize on:
private final static Object lock = new Object();
private static int common = 0;
...
synchronized (lock) {
common++;
}
It might be better in this specific case, you might consider using an AtomicInteger. That allows you do something like the following without any synchronization.
private static AtomicInteger common = new AtomicInteger(0);
...
// no need to synchronize since that is handled by the class
common.incrementAndGet();
来源:https://stackoverflow.com/questions/10309015/learning-to-use-threads-that-prevent-data-race-conditions