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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. public class TicketDemo {
  2.         public static void main(String[] args) {
  3.                 Ticket t = new Ticket();
  4.                 Thread t0 = new Thread(t);
  5.                 Thread t1 = new Thread(t);
  6.                 t0.setName("窗口一:");
  7.                 t1.setName("窗口二:");
  8.                 t0.start();
  9.                 t1.start();
  10.         }
  11. }

  12. class Ticket implements Runnable {
  13.         private int num = 100;
  14.         public void run() {
  15.                 while(true) {
  16.                         try {
  17.                                 sell();
  18.                         } catch (InterruptedException e) {
  19.                                 e.printStackTrace();
  20.                         }
  21.                 }
  22.         }
  23.        
  24.         public void sell() throws InterruptedException {
  25.                 if(num>0) {
  26.                         Thread.sleep(10);
  27.                         System.out.println(Thread.currentThread().getName()+"卖票啦,卖票啦"+num--);
  28.                 }
  29.         }
  30. }
复制代码
我知道会产生安全问题,会出现0号票,不安全。但是我在运行的时候突然发现有两个同号的票,这个问题是怎么产生的。
窗口一卖票啦,卖票啦80
窗口二卖票啦,卖票啦80
窗口二卖票啦,卖票啦79
窗口一卖票啦,卖票啦78
窗口二卖票啦,卖票啦77
窗口一卖票啦,卖票啦76
窗口一卖票啦,卖票啦75
为什么会出现两个80号票呢?
是 num--在运行后给num赋值期间出现的问题吗?
如果分开写
System.out.println(Thread.currentThread().getName()+"卖票啦,卖票啦"+num);
num--;这样我知道是两条语句出现问题,
但是System.out.println(Thread.currentThread().getName()+"卖票啦,卖票啦"+num--);这不是一条语句吗为什么还会出现问题。
具体System.out.println(Thread.currentThread().getName()+"卖票啦,卖票啦"+num--);这条语句在多线程期间是怎么出现同号票安全问题的原因的,麻烦给解释下

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1 赞一个!

查看全部评分

5 个回复

倒序浏览
你的程序没有加线程同步呀,有时候可能看不到问题,但有时候会出问题。加上线程同步就可以了。、

回复 使用道具 举报
弄不大明白这个打印线程+num--,在内存中到底是具体怎么执行的
回复 使用道具 举报
本帖最后由 王震阳 于 2012-10-10 13:28 编辑
  1. public class TicketDemo {
  2.         public static void main(String[] args) {
  3.                 Ticket t = new Ticket();
  4.                 Thread t0 = new Thread(t);
  5.                 Thread t1 = new Thread(t);
  6.                 t0.setName("窗口一11111111111111:");
  7.                 t1.setName("窗口二222:");
  8.                 t0.start();
  9.                 t1.start();
  10.         }
  11. }

  12. class Ticket implements Runnable {
  13.         private int num = 1000;//为了测试效果,将票数改为1000张
  14.                 Object obj=new Object();//定义一个object对象
  15.         public void run() {
  16.                 while(true) {
  17.                                         synchronized(obj)//在这个地方加了一个同步锁
  18.                                         {
  19.                         try {
  20.                                 sell();
  21.                         } catch (InterruptedException e) {
  22.                                 e.printStackTrace();
  23.                         }
  24.                                         }
  25.                 }
  26.         }
  27.         
  28.         public void sell() throws InterruptedException {
  29.                 if(num>0) {
  30.                         Thread.sleep(10);
  31.                         System.out.println(Thread.currentThread().getName()+"卖票啦,卖票啦"+num--);
  32.                 }
  33.         }
  34. }


  35. 运行截图:

复制代码
回复 使用道具 举报
王震阳 发表于 2012-10-10 13:08
你的程序没有加线程同步呀,有时候可能看不到问题,但有时候会出问题。加上线程同步就可以了。、

...

我知道可能出现问题,但是分析不出来为什么会出现同一张票的问题,郁闷
回复 使用道具 举报
本帖最后由 王震阳 于 2012-10-10 13:32 编辑

[quote]徐传任 发表于 2012-10-10 13:17 http://edu.csdn.net/main/feature/bxd_25.shtml

你把第十一天的下载下来就知道了。

你的问题的主要解释为:因为cpu的执行不是连续的,每个线程都分配了执行时间,交换进行的,当第一个进程判断为true是,可能cpu就改换另一个进程了,
导致线程而也判断为true,这样两个线程都出售了同一张票。因此我们要解决这个方法就是,当线程1进入判断是,我们加一个锁,当线程1出来时再解锁,这样会降低系统运行的效率,
但是提高了安全性,或者说,类似于售票的问题,必须有线程安全方面的考虑。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马