我正在学习Java的并发基础知识,并且在下面的示例中遇到一个问题。有两个线程应同时运行并完成它们在某些全局静态对象上的循环。我希望一个线程可以在另一个线程之前完成并输出不同的值,但是我不希望看到两个线程都打印相同的值,这表明它们在打印输出之前都没有完成循环。
代码:
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 Accum {
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public int getCount() {
return counter;
}
public void updateCounter(int add) {
counter += add;
}
}
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("index in one = " + x);
}
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("index in two = " + x);
}
System.out.println("two " + a.getCount());
}
}
为什么会这样?当我尝试调试打印语句(在上面的代码中作了注释)时,一切开始按预期工作。
我的输出:(每次都不同,这也很奇怪)
一个82067 两个82067
这实际上是《 Head First Java》(第二版)一书中的代码难题,但作者提供了与上述相同的代码来解决不同的行为。
图书输出:(与上面相同的代码)
一个98098两个98099
书籍说明:
来自两个不同类的线程正在更新同一对象 第三类,因为两个线程都在访问一个的实例 累积。
总而言之,我的问题是:
**-附加
答案 0 :(得分:2)
不知道这本书是如何工作的,但是您的Accum实例不是线程安全的。因此,每次运行它时,您都会得到不同的答案。如果使updateCounter()和getCount()同步,它应该可以可靠地工作。