谁可以解释结果?

时间:2019-10-29 02:57:32

标签: java multithreading

public class Bank {
    private  int sum=0;

    public void add(int n) {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sum+= n;

        System.out.println(sum);
    }
}


public class Consumer implements Runnable {

    Bank bank = new Bank();
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            bank.add(100);
        } 
    }
}

public class Tes2 {
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        Thread thread1 = new Thread(consumer);
        Thread thread2 = new Thread(consumer);
        thread1.start();
        thread2.start();
    }
}

这是一个多线程程序,模拟是向银行的多个存款人存款,用于演示多线程安全问题。由于代码不同步,因此其第一和第二结果可能是200 / 200,200 / 300,依此类推。但是我不明白为什么你会得到100/100,谁能解释?

2 个答案:

答案 0 :(得分:3)

如果仅基于代码中的行来考虑该程序的并发性,则100/100输出结果将毫无意义。但是,您还必须考虑执行这些行时实际上正在发生什么指令。每行代码可以包含许多汇编指令。在这种情况下,要将n添加到sum,实际上发生的是从存储器中读取sum的值,可能将其加载到寄存器中,然后递增,然后重新写入存储器中。

在以下情况下可能会发生100/100输出。假设线程1和线程2都调用bank.add(100),并且库异步处理请求。也就是说,银行有一个处理每个请求的线程。

然后,存储区的线程1加载sum的值,该值为零。线程2也紧随其后加载sum的值,该值仍为零。然后,线程1获得它加载的值,将n=100加起来,然后将其写入内存。线程2执行相同的操作;它采用先前加载的总和的值,0,加100,然后写回内存。然后,它们各自打印出100的值。

答案 1 :(得分:3)

这是比赛条件。

两个线程都可以求和。

sum + = n;不是原子的

线程1读取总和0

线程2换入,因为未同步的代码将sum读取为0

线程1将100加到0,并将其写入总和

线程2将100加0并将其写入以求和覆盖线程1s的值