多线程中出现的一个的奇怪现象

xun_ying 2014-02-25 10:21:05

class Bank
{
private int sum = 0;
public void add(int n)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
}
sum = sum + n;
System.out.println(Thread.currentThread().getName()+"sum="+ sum);
// System.out.println(sum);
}
}

class Cus implements Runnable
{
Bank bank = new Bank();
public void run()
{
for(int x= 1; x <=3; x++)
bank.add(100);
}
}

public class BankDemo
{
public static void main(String args[])
{
Cus c = new Cus();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();

}
}




为什么会出现以下的现象








...全文
395 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
gdtdream 2014-03-01
  • 打赏
  • 举报
回复
线程同步安全。还差一步synchronized你就会明白了。。。
敌敌畏耶 2014-02-28
  • 打赏
  • 举报
回复
关于多线程的还应该去理解一下 里面的 锁(synchronized等等)问题···
永不言败snow 2014-02-28
  • 打赏
  • 举报
回复
由于没有考虑到线程同步问题,可以想象为当两个线程同时执行到这里的时候(几乎同时)sum = sum + n; 当后面的sum+n两个线程都执行之后,然后又同时赋值给sum, 其实是有先后,但是都是在赋值给sum之前执行的,所以就当做同时,所以两个人拿到的值一样。
saraluckly 2014-02-28
  • 打赏
  • 举报
回复
你这个奇怪结果也只是一种可能的结果;你多运行几次或修改Thread.sleep(10)的值运行下,也许就有不同的结果; 其实关键是 sum = sum + n; 别看这个只有一条程序语句,实际这里有三条指令: 1、读取sum; 2、sum加n; 3、再赋值sum; 也就是说这个操作不是原子操作; 从上面也就可以知道:为什么会出现两个100 当线程0读取sum为0,再加100,这时线程0中断,线程1读取sum为0,再加100,线程1再中断,线程0赋值sum为100,线程0中断,线程1赋值sum为100,这样就出现了两个100; 至于最终是500,自己可以分析了; 上面的很好的解释 赞一个
sca4441479 2014-02-28
  • 打赏
  • 举报
回复
楼上都说的很明白了,结贴吧!
acmsong 2014-02-28
  • 打赏
  • 举报
回复
两个线程都在操作sum变量,执行的顺序是由CPU决定的。加synchornized,可以保证同一时刻只被一个线程用。
乔不思 2014-02-28
  • 打赏
  • 举报
回复
你的 线程 不安全,关于两个100的问题:当你的一个线程执行的时候,另外一个线程已经读取了 这个线程还没有修改的数据(也就是说,他们读取的数据是一样的),那么他们执行后都打印出来的结果也是一样的, 那个这个时候的数据就是100,然后他们就在100的基础上进行并发执行,,,应该每次运行的结果都有出入,不一样。。 想让他安全,java有synchornized关键字,java1.5后又推出了,lock,这个运用更方便。。建议楼主看看
houshen13828468384 2014-02-27
  • 打赏
  • 举报
回复
不好意思,要把System.out.println也加到同步块去,这个也不是线程安全的 synchronized (this.getClass()) { sum = sum + n; System.out.println(Thread.currentThread().getName()+"sum="+ sum); }
houshen13828468384 2014-02-27
  • 打赏
  • 举报
回复
很简单啊,你的bank被共享了, sum = sum + n;这里加个同步块就安全了啊
lliiqiang 2014-02-26
  • 打赏
  • 举报
回复
线程执行是随机的,虽然有的是极少数,但是人一般不会发现它.
xun_ying 2014-02-25
  • 打赏
  • 举报
回复
引用 2 楼 zuoziji_lj 的回复:
去看看java线程安全
正在看,
xun_ying 2014-02-25
  • 打赏
  • 举报
回复
引用 4 楼 happy7023 的回复:
两个thread中引用的sum都是c.bank.sum,开始的两个100是由于是由于bank被初始化了两次,新手,个人理解
bank 应该是属于两个线程共享的把,
xun_ying 2014-02-25
  • 打赏
  • 举报
回复
引用 3 楼 skyman1991 的回复:
线程同步的问题
public synchronized void add(int n)
    {
        try
        {
            Thread.sleep(10);
        }
        catch (Exception e)
        {
        }
        sum = sum + n;
        System.out.println(Thread.currentThread().getName()+"sum="+  sum);
    //    System.out.println(sum);
    }
嗯嗯啊,知道是线程同步问题,只是想仔细了解这中间程序代码的走向,在打印100 100 .. 的之前不是都有——+100 两次 了么,,,且为什么最终是500
东海小龙 2014-02-25
  • 打赏
  • 举报
回复
线程问题。得到的结果是随机的。
airy 2014-02-25
  • 打赏
  • 举报
回复
两个thread中引用的sum都是c.bank.sum,开始的两个100是由于是由于bank被初始化了两次,新手,个人理解
Magician-CH 2014-02-25
  • 打赏
  • 举报
回复
线程同步的问题
public synchronized void add(int n)
    {
        try
        {
            Thread.sleep(10);
        }
        catch (Exception e)
        {
        }
        sum = sum + n;
        System.out.println(Thread.currentThread().getName()+"sum="+  sum);
    //    System.out.println(sum);
    }
卡卡吉利 2014-02-25
  • 打赏
  • 举报
回复
去看看java线程安全
xun_ying 2014-02-25
  • 打赏
  • 举报
回复
为什么会出现两个100,,且最终是500,
xiaoran27 2014-02-25
  • 打赏
  • 举报
回复
结果是随机的, 你多跑几次就可以发现了.
lxbccsu 2014-02-25
  • 打赏
  • 举报
回复
你这个奇怪结果也只是一种可能的结果;你多运行几次或修改Thread.sleep(10)的值运行下,也许就有不同的结果; 其实关键是 sum = sum + n; 别看这个只有一条程序语句,实际这里有三条指令: 1、读取sum; 2、sum加n; 3、再赋值sum; 也就是说这个操作不是原子操作; 从上面也就可以知道:为什么会出现两个100 当线程0读取sum为0,再加100,这时线程0中断,线程1读取sum为0,再加100,线程1再中断,线程0赋值sum为100,线程0中断,线程1赋值sum为100,这样就出现了两个100; 至于最终是500,自己可以分析了;
加载更多回复(1)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧