我不明白为什么每次运行此代码都会得到不同的答案? 正确的答案应该是一个98098和两个98099。任何人都有任何想法为什么不能这样工作?例如,一次答案返回“一个49047两个90047”,然后又一次返回“一个40072两个40072”。我现在很困惑,也没有任何合理的解释
public class TestThreads {
public static void main(String[] args){
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 98; x++){
a.updateCounter(1000);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("one " + a.getCount());
}
}
class ThreadTwo implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 99; x++){
a.updateCounter(1);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("two " + a.getCount());
}
}
class Accum {
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
private int counter = 0;
public int getCount(){
return counter;
}
public void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
答案 0 :(得分:1)
由于有两个线程在没有线程安全的情况下更新同一数据,因此一个线程很容易覆盖另一个线程设置的值。
每个线程都使用其自己的线程缓存值。例如
线程1加1一百次。它的值为100
线程2加1000一百次。它的值为100000
此时,选择一个值。说这是线程1的值。
线程1加1一百次。它的值为200
线程2加1000一百次。它的值为100100
这次,选择线程2的值。
最后,平均保留了一半的更新,因为选择的值有些随机。
答案 1 :(得分:1)
您可以通过将Accum中的方法声明为已同步来获得98099。
这将确保每次只有一个线程可以访问其信息。
正如其他答案所指出的那样,您将获得意想不到的结果,因为没有什么可以阻止每个线程覆盖另一个线程所做的事情。
尝试一下:
class Accum {
private static Accum a = new Accum();
public static synchronized Accum getAccum(){
return a;
}
private int counter = 0;
public synchronized int getCount(){
return counter;
}
public synchronized void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
答案 2 :(得分:0)
您的问题是这个
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
由于其为STATIC,因此所有线程仅共享一个实例。因此,当您在一个线程中设置它时,所有线程都会获得相同的新值。如果您删除了静态通知程序并为每个线程实例化一个Accum类的新对象,那么它将起作用。