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 回答
撒科打诨
TA贡献1934条经验 获得超2个赞
这是一个竞争条件。
两个线程都可以访问 sum。
总和+=n;不是原子的
线程 1 读取 sum 0
线程 2 换入,因为代码未同步,读取 sum 为 0
线程 1 将 100 加到 0 并将其写入总和
线程 2 将 0 加 100 并将其写入总和并覆盖线程 1 的值
神不在的星期二
TA贡献1963条经验 获得超6个赞
如果您仅根据代码中的行来考虑该程序的并发性,那么 100/100 的输出结果就没有意义。但您还必须考虑执行这些行时实际发生的指令是什么。每行代码可以包含很多很多汇编指令。在这种情况下,要添加n
到sum
,真正发生的是从内存中读取 的值sum
,可能加载到寄存器中,递增,然后重新写入内存中。
100/100 输出可能发生在以下场景中。假设线程 1 和线程 2 都调用bank.add(100)
,并且银行异步处理请求。也就是说,银行有一个线程处理每个请求。
然后,该组的线程 1 加载 的值sum
,该值为零。线程 2 还加载了紧随其后的值sum
,该值仍然为零。然后,线程 1 获取它加载的值,添加n=100
,并将其写入内存。线程2做同样的事;它采用之前加载的 sum 值 0,加上 100,然后将其写回内存。然后,他们各自打印出 100 的值。
添加回答
举报
0/150
提交
取消