两个线程在循环中错过了值

时间:2021-12-07 00:25:34

I have code like this:

我有这样的代码:

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;
    }
}

There are two threads and they add 1 to value of n (in static class). When I run this code, the value of n value is never equal to 400000 but something about that. Why something like this is happening?

有两个线程,它们将n的值加1(在静态类中)。当我运行这段代码时,n值的值永远不会等于400000,而是相关的。为什么会发生这样的事情?

3 个解决方案

#1


3  

This is one of the basic problems of multithreading. Getting a value, incremening it and storing it back is not what is called 'atomic' - that is, multiple operations are required to do this. What happens here is: One thread obtains N at value X, the other thread does so as well. Both threads increment, and store X+1 as new N - although both incremented their local count by one, N was also just incremented by one.

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

Whether or not this happens and how much N will deviate from the expected value is, for arguments sake, random.

为了论证,这是否发生以及N将偏离预期值多少是随机的。

Check out classes like AtomicInteger and read up on things called mutexes.

查看像AtomicInteger这样的类,并阅读有关互斥体的内容。

#2


1  

Race condition occurring. See synchronized statement (below) ...

发生种族情况。请参见synchronized语句(如下)...

public void run() {
    int temp;
    for (int i = 0; i < 200000; i++) {
        synchronized(n) {
          temp = n.getN();
          n.setN(temp + 1);
        }
    }
}

#3


0  

Simple answer to your question is because invocation of the n.getN() and n.setN(temp + 1) performed by both threads interleaves each other, for example:

对你的问题的简单回答是因为两个线程执行的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

You need to implement thread synchronization or other method to achieve the intended result.

您需要实现线程同步或其他方法来实现预期的结果。

I recommend you spend some time on Concurrency chapter on Java SE Tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

我建议您花一些时间在Java SE教程的Concurrency章节:http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

#1


3  

This is one of the basic problems of multithreading. Getting a value, incremening it and storing it back is not what is called 'atomic' - that is, multiple operations are required to do this. What happens here is: One thread obtains N at value X, the other thread does so as well. Both threads increment, and store X+1 as new N - although both incremented their local count by one, N was also just incremented by one.

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

Whether or not this happens and how much N will deviate from the expected value is, for arguments sake, random.

为了论证,这是否发生以及N将偏离预期值多少是随机的。

Check out classes like AtomicInteger and read up on things called mutexes.

查看像AtomicInteger这样的类,并阅读有关互斥体的内容。

#2


1  

Race condition occurring. See synchronized statement (below) ...

发生种族情况。请参见synchronized语句(如下)...

public void run() {
    int temp;
    for (int i = 0; i < 200000; i++) {
        synchronized(n) {
          temp = n.getN();
          n.setN(temp + 1);
        }
    }
}

#3


0  

Simple answer to your question is because invocation of the n.getN() and n.setN(temp + 1) performed by both threads interleaves each other, for example:

对你的问题的简单回答是因为两个线程执行的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

You need to implement thread synchronization or other method to achieve the intended result.

您需要实现线程同步或其他方法来实现预期的结果。

I recommend you spend some time on Concurrency chapter on Java SE Tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

我建议您花一些时间在Java SE教程的Concurrency章节:http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html