问题
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