A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈世涛 中级黑马   /  2012-7-22 08:54  /  2482 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


class Bank
{
private int sum;
public void add(int num)
{
  sum = sum + num;
  System.out.println("sum="+sum);
}
}
class Cus implements Runnable
{
Bank b = new Bank();
public void run()
{
  
  for(int x=0; x<3; x++)
  {
   b.add(100);
  }
}
}

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();
}
}
运行结果如下:



求原理,求详解,求真相。。。

谢谢。
   

1.PNG (73.98 KB, 下载次数: 32)

1.PNG

8 个回复

倒序浏览
多线程运行出现了安全问题。
多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分
你是不是没往下看。建议看 毕向东 11天-09多线程问题。
你就知道了



class Bank
{
        private int sum;
        //Object obj = new Object();
        public synchronized void add(int n)  //用synchronized同步代码块处理
        {
                //synchronized(obj)
                //{
                        sum = sum + n;
                        try{Thread.sleep(10);}catch(Exception e){}///这边加上看看。
                        System.out.println("sum="+sum);
                //}
        }
}

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


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();
        }
}
回复 使用道具 举报
本帖最后由 全海波 于 2012-7-22 13:11 编辑
  1. class Bank
  2. {
  3.         private int sum;
  4.         public void add(int num)
  5.         {
  6.                 //第六步:每个储户的钱开始累加
  7.                 sum = sum + num;
  8.                 /*
  9.                     第七步:这步是你打印出的结果的关键问题所在,也是原理所在!!!!
  10.                     在这里线程执行到这步的时候,线程“1已经运算了一次,sum的值这时为100,
  11.                     但在此时”线程“1”往下执行的时候有可能在这里悬挂,也就是说
  12.                     该线程有可能进入阻塞状态(临时状态),等线程“1”进入临时状态的时候,
  13.                     这个计算结果还没能够打印,线程“2”这时候也进入了,计算并累加上一次的结果,
  14.                     计算完后,打印结果,这时候,线程“1”重新获得了执行权,开始执行打印结果,结果发现
  15.                     sum的值已经从原来的100变成要现在要打印200了,这就是为什么出现这种结果了
  16.                */
  17.                 System.out.println("sum="+sum);
  18.         }
  19. }
  20. class Cus implements Runnable
  21. {
  22.         Bank b = new Bank();
  23.         //第四步:线程1,2分别进入循环阶段,储户开始往Bank存钱
  24.         public void run()
  25.         {
  26.                 for(int x=0; x<3; x++)
  27.                 {
  28.                         //第五步:调用add方法,每个储户每次存入一百元
  29.                          b.add(100);
  30.                 }
  31.         }
  32. }

  33. class BankDemo
  34. {
  35.         public static void main(String[] args)
  36.         {
  37.                 //第一步:主线程进入,创建Cus对象
  38.                 Cus c = new Cus();
  39.                 //第二步:接下来创建线程1 ,2,此时线程被创建,但是没有执行
  40.                 Thread t1 = new Thread(c);
  41.                 Thread t2 = new Thread(c);
  42.                 //第三步:线程1,2开始执行,调用run方法
  43.                 t1.start();
  44.                 t2.start();
  45.         }
  46. }
复制代码
希望可以解决你的疑惑,您的疑惑被解决,是我最大的快乐!

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
线程的同步问题:在run方法加上关键字synchronized就可以了,试试下面的代码撒,希望可以解决你的疑问
class Bank
{
private int sum;
public void add(int num)
{
  sum = sum + num;
  System.out.println("sum="+sum);
}
}
class Cus implements Runnable
{
Bank b = new Bank();
public synchronized void run()//控制线程的进度,一个执行完在一个,这样就会稳定的输出了
{
  
  for(int x=0; x<3; x++)
  {
   b.add(100);
  }
}
}

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();
}
}
-----------------------------------------------------------------------------------------------------华丽的分割线----------------------------------------------------------------------------------------------------------------------------------------------------
也可以使用同步代码块完成:
class Bank {
private int sum;
public void add(int num) {
  sum = sum + num;
  System.out.println("sum=" + sum);
}
}
class Cus implements Runnable {
Bank b = new Bank();
public void run()
{
  synchronized (this) {
   for (int x = 0; x < 3; x++) {
    b.add(100);
   }
  }
}
}
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();
}
}
结果:


回复 使用道具 举报
郭凯敏 发表于 2012-7-22 14:43
线程的同步问题:在run方法加上关键字synchronized就可以了,试试下面的代码撒,希望可以解决你的疑问
clas ...

哥们,别乱答,别人要的是原因,不是另一个解决方法!
回复 使用道具 举报
哥们,原因你不是告诉,我还多说什么,我就是也告诉他解决方法,知道原因知道解决方法,这不更好?这叫乱答?真搞笑
回复 使用道具 举报
全海波 发表于 2012-7-22 15:00
哥们,别乱答,别人要的是原因,不是另一个解决方法!

哥们,原因你不是告诉,我还多说什么,我就是也告诉他解决方法,知道原因知道解决方法,这不更好?这叫乱答?真搞笑
回复 使用道具 举报
王飞 中级黑马 2012-7-22 15:36:57
8#
图解来了,

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
class Bank
{
private int sum;
public synchronized void add(int num)//这里应该加同步,不加同步的话有可能发生安全问题
{                                    //当线程执行到sum = sum + num;的时候有可能cup切换到
                                         //另一个线程去执行,并没有来的急打印出来,所以会出现你所看到的问题
   sum = sum + num;                  //加上同步之后就会执行完了之后下一个线程才能执行,就解决了问题
   System.out.println("sum="+sum);
}
}
class Cus implements Runnable
{
Bank b = new Bank();
public void run()
{
   
   for(int x=0; x<3; x++)
   {
    b.add(100);
   }
}
}

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();
}
}
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马