-1

我有这样的代码:

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,而是与此有关。为什么会发生这样的事情?

4

3 回答 3

3

这是多线程的基本问题之一。获取一个值、增加它并将其存储回来并不是所谓的“原子”——也就是说,需要多个操作才能做到这一点。这里发生的情况是:一个线程在值 X 处获得 N,另一个线程也这样做。两个线程都递增,并将 X+1 存储为新的 N - 尽管两者都将其本地计数递增 1,但 N 也仅递增 1。

无论这种情况是否发生以及 N 会偏离预期值多少,出于争论的原因,都是随机的。

查看 AtomicInteger 之类的类并阅读称为互斥体的内容。

于 2013-01-01T23:52:51.267 回答
1

出现竞态条件。请参阅同步语句(如下)...

public void run() {
    int temp;
    for (int i = 0; i < 200000; i++) {
        synchronized(n) {
          temp = n.getN();
          n.setN(temp + 1);
        }
    }
}
于 2013-01-02T00:00:01.170 回答
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

于 2013-01-02T00:28:52.840 回答