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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 郭宁 中级黑马   /  2012-5-18 00:55  /  2209 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 郭宁 于 2012-5-18 01:01 编辑
  1. class Ticker implements Runnable{

  2.         private  int tick = 20; //这里加不加 static 多次运行就会出现 售出了两个 20
  3.                                                         //按我的思想 在 main函数中创建线程 传的都是 t1 这里不用静态就可以了吧
  4.                                                         //                        Thread th1 = new Thread(t1);
  5.                                                         //                        Thread th2 = new Thread(t1);
  6.         @Override
  7.         public void run() {
  8.                 // TODO Auto-generated method stub
  9.                 while(true)
  10.                 {
  11.                         if(tick > 0)
  12.                         {
  13.                                 System.out.println(Thread.currentThread().getName()+"售出:"+tick--);
  14. //                               若把输出语句改成下面,多次运行 会出现如下结果:售出了一个 0号票,没有售出 2号票
  15. //                                System.out.println(Thread.currentThread().getName()+"售出:"+tick);
  16. //                                tick--;
  17.                                 
  18. //                                Thread-0售出:20
  19. //                                Thread-1售出:20
  20. //                                Thread-0售出:19
  21. //                                Thread-1售出:18
  22. //                                Thread-0售出:17
  23. //                                Thread-1售出:16
  24. //                                Thread-0售出:15
  25. //                                Thread-0售出:13
  26. //                                Thread-0售出:12
  27. //                                Thread-0售出:11
  28. //                                Thread-0售出:10
  29. //                                Thread-0售出:9
  30. //                                Thread-0售出:8
  31. //                                Thread-0售出:7
  32. //                                Thread-0售出:6
  33. //                                Thread-0售出:5
  34. //                                Thread-0售出:4
  35. //                                Thread-1售出:14
  36. //                                Thread-0售出:3
  37. //                                Thread-0售出:1
  38. //                                票已售完!!
  39. //                                Thread-1售出:0
  40. //                                票已售完!!

  41.                                 
  42.                         }
  43.                         else
  44.                         {
  45.                                 System.out.println("票已售完!!");
  46.                                 break;
  47.                         }
  48.                 }
  49.         }
  50.         
  51. }

  52. public class TickerDemo{
  53.         public static void main(String[] args)
  54.         {
  55.                 Ticker t1 = new Ticker();
  56.                
  57.                 Thread th1 = new Thread(t1);
  58.                 Thread th2 = new Thread(t1);
  59.                 th1.start();
  60.                 th2.start();
  61.         }
  62. }
复制代码
问题都在代码里面~ 求高人指点一下为何会出现这种情况!!

4 个回复

倒序浏览
      多线程问题,当有多线程处理共享数据时需要同步处理安全问题。
这里的问题是,多线程有随机性,第一次当t1执行完    System.out.println(Thread.currentThread().getName()+"售出:"+tick);后, 就会 打印“Thread-0售出:20”,如果此时CUP执行权被t2线程抢走了,那么t1就停在“tick--;”之前,也就是没有执行tick自减,此时tick的值还是20,然后t2线程执行了“System.out.println(Thread.currentThread().getName()+"售出:"+tick);”,也就是打印了“Thread-1售出:20”,所以问题就是这样出现了。下面的也是根据线程的随机性分析就行了

回复 使用道具 举报
楼主的多线程都学完了么?还是正在学?

这里出现了线程同时修改共享数据的情况。楼主的两个线程共用一个资源t1,那么同时共用t1中的tick成员。
两个线程并发修改一个共享数据区域或者数据单元,就会出现更新覆盖的情况。
说简单点,就是这样的:
因为现在的计算机都是多道程序系统,CPU执行作业的时候是并发的,每一个线程都在切换中运行着。
比如:假设tick=20
当线程th1正执行到
System.out.println(Thread.currentThread().getName()+"售出:"+tick);的时候   //输出20
tick--;还没来得及执行,
就切换到th2的System.out.println(Thread.currentThread().getName()+"售出:"+tick);  //输出20
因此输出了相同的数据。
如果th1:tick--之后,马上又执行th2:tick--,这下就少输出了一个数据19,tick就变成18了。

我举出的只是楼主代码错误的一部分,楼主的代码可以把tick改成1000,多运行几次,你就发现每次结果都不一样了。
正确代码改成下面形式
  1. while(true){
  2.                     synchronized (this) {
  3.                                         if(tick > 0){
  4.                             System.out.println(Thread.currentThread().getName()+"售出:"+tick--);                 
  5.                     }
  6.                     else{
  7.                             System.out.println("票已售完!!");
  8.                             break;
  9.                     }
  10.                                 }     
  11.             }
复制代码
希望能帮到你,仔细把视频看了就会了解了。
回复 使用道具 举报
潘东升 发表于 2012-5-18 01:31
多线程问题,当有多线程处理共享数据时需要同步处理安全问题。
这里的问题是,多线程有随机性,第一 ...

谢啦,明白了! 我刚学到这一章!
回复 使用道具 举报
云惟桉 发表于 2012-5-18 01:42
楼主的多线程都学完了么?还是正在学?

这里出现了线程同时修改共享数据的情况。楼主的两个线程共用一个资 ...

谢啦,明白了! 我刚学到这一章!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马