黑马程序员技术交流社区

标题: 多线程买票问题 [打印本页]

作者: 黑马-张扬    时间: 2012-12-2 17:08
标题: 多线程买票问题
下面这个例子是一个多线程买票的错误示例:

public class SaleTicketMutiThread implements Runnable {
int tickets = 100;
int temp = tickets;
boolean flag = true;
@Override
public void run() {
   while (flag) {
    if (tickets > 0) {
     try {
      Thread.sleep(30);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     sale();
    } else {
     flag = false;
     System.out.println(Thread.currentThread().getName() + "卖光了");
    }
   }
}
public synchronized void sale() {
   tickets--;
   System.out.println(Thread.currentThread().getName() + " 已卖"
     + (temp - tickets) + "张,系统还剩" + tickets + "张票");
}
/**
   * @param args
   */
public static void main(String[] args) {
   SaleTicketMutiThread st = new SaleTicketMutiThread();
   new Thread(st, "一号窗口").start();
   new Thread(st, "二号窗口").start();
   new Thread(st, "三号窗口").start();
   new Thread(st, "四号窗口").start();
}
}

最后会运行出的结果会出现负数:
......
四号窗口 已卖99张,系统还剩1张票
一号窗口 已卖100张,系统还剩0张票
一号窗口卖光了
三号窗口 已卖101张,系统还剩-1张票
四号窗口 已卖102张,系统还剩-2张票
二号窗口 已卖103张,系统还剩-3张票

我的疑问:
我想问的是 一号窗口线程 取得了 共享变量tickets 的时候, 二、三、四号窗口线程也取得了tickets, 即使这时候一号窗口线程 调用了 sale 方法 对其进行 tickets -- 操作,   二、三、四号窗口线程取得了tickets还是先前的,没有执行tickets -- 操作 ;
作者: 轻松过关    时间: 2012-12-2 17:24
public class SaleTicketMutiThread implements Runnable {
int tickets = 5;
int temp = tickets;
boolean flag = true;
@Override
public void run() {
    while (flag) {
            sale();
    }
}
public synchronized void sale() {
     if (tickets > 0) {
             try {
                   Thread.sleep(30);
                  } catch (InterruptedException e) {
                  e.printStackTrace();
                  }
             tickets--;
                System.out.println(Thread.currentThread().getName() + " 已卖"
                  + (temp - tickets) + "张,系统还剩" + tickets + "张票");
     } else {
      flag = false;
      System.out.println(Thread.currentThread().getName() + "卖光了");
     }
   
}
/**
    * @param args
    */
public static void main(String[] args) {
    SaleTicketMutiThread st = new SaleTicketMutiThread();
    new Thread(st, "一号窗口").start();
    new Thread(st, "二号窗口").start();
    new Thread(st, "三号窗口").start();
    new Thread(st, "四号窗口").start();
}
}
作者: 轻松过关    时间: 2012-12-2 17:26
主要是你同步的代码问题,上面的if (tickets > 0) 判断也要写进同步代码块。否则现场判断时还是0之前的数据。
作者: 轻松过关    时间: 2012-12-2 17:29
else {
      flag = false;
      System.out.println(Thread.currentThread().getName() + "卖光了");
     }
这句话不被同步保护,当tickets《0时 每个线程都会打印一次。
作者: 洪灿阳    时间: 2012-12-3 09:53
线程没有完全进行同步,else 里面的flag并不是对于所有的线程都同步啊,这个修改下,就行了。
package cn.itcast.Test;

public class ThreadTest3 {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                 SaleTicketMutiThread st = new SaleTicketMutiThread();
                   new Thread(st, "一号窗口").start();
                   new Thread(st, "二号窗口").start();
                   new Thread(st, "三号窗口").start();
                   new Thread(st, "四号窗口").start();
        }
       
        //下面这个例子是一个多线程买票的错误示例:

}
class SaleTicketMutiThread implements Runnable {
        int tickets = 100;
        int temp = tickets;
        boolean flag = true;
        @Override
        public void run() {
           while (flag) {
           /* if (tickets > 0) {
             try {
              Thread.sleep(30);
             } catch (InterruptedException e) {
              e.printStackTrace();
             }
             sale();
            } else {
            // flag = false;
             System.out.println(Thread.currentThread().getName() + "卖光了");
            
           }*/
                   sale();
           }
        }
        public synchronized void sale() {
          
           if(tickets>0){
                   tickets--;
                   System.out.println(Thread.currentThread().getName() + " 已卖"
                     + (temp - tickets) + "张,系统还剩" + tickets + "张票");
           }
           else
                   flag=false;
          
        }
}




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2