我有这样的代码:
public class Count extends Thread {
static IntCell n = new IntCell();
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
p.setName("Watek1");
Count q = new Count();
p.start();
q.start();
try {
p.join();
q.join();
}
catch (InterruptedException e) {
System.out.println(e);
}
System.out.println("The value of n is " + n.getN());
}
}
class IntCell {
private int n = 0;
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
}
有两个线程,它们将n的值加1(在静态类中)。当我运行这段代码时,n值的值永远不会等于400000,而是相关的。 为什么会发生这样的事情?
答案 0 :(得分:3)
这是多线程的基本问题之一。获取值,增加值并将其存储回来并不是所谓的“原子” - 也就是说,需要多次操作才能执行此操作。这里发生的是:一个线程在值X处获得N,另一个线程也在这样做。两个线程都递增,并将X + 1存储为新的N - 尽管它们的本地计数都增加了1,N也只增加了一个。
为了论证,这是否会发生以及N将偏离预期值的多少是随机的。
查看像AtomicInteger这样的类,并阅读有关互斥锁的内容。
答案 1 :(得分:1)
发生种族情况。参见synchronized语句(如下)......
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
synchronized(n) {
temp = n.getN();
n.setN(temp + 1);
}
}
}
答案 2 :(得分:0)
对您的问题的简单回答是因为两个线程执行的 n.getN()和 n.setN(temp + 1)的调用相互交错,例如:
Thread 1: n.getN() // returns 100
Thread 2: n.getN() // also returns 100
Thread 1: n.setN(temp + 1) // sets 101
Thread 2: n.setN(temp + 1) // also sets 101
您需要实现线程同步或其他方法来实现预期的结果。
我建议您花一些时间在Java SE教程的并发章节:http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html