问题描述
下面的代码应该通过在common上使用synced方法来防止Data Racing.但是由于某种原因,输出始终为19915-19980.如果不是数据竞速,那不应该是20000吗?
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);
}
}
推荐答案
您正在尝试在自动装箱的对象上进行同步,该对象每次都是不同的对象.
You are trying to synchronize on an auto-boxed object that will be a different object every time.
synchronized((Integer)common){
重点是要在每个线程中的同一对象上进行同步.即使将common
设置为Integer
,将其分配给另一个值后,它也会是另一个对象.
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++;
}
在这种特定情况下可能会更好,您可以考虑使用AtomicInteger
.这样一来,您无需进行任何同步即可执行以下操作.
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();
这篇关于学习使用防止数据争用情况的线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!