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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© che201311 中级黑马   /  2013-11-21 22:27  /  1882 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

public class Ticket {

public static void main(String[] args){

Loket l1 = new Loket(1);
Loket l2 = new Loket(2);
Loket l3 = new Loket(3);
Loket l4 = new Loket(4);
Loket l5 = new Loket(5);
Thread t1 = new Thread(l1);
Thread t2 = new Thread(l2);
Thread t3 = new Thread(l3);
Thread t4 = new Thread(l4);
Thread t5 = new Thread(l5);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}


}

class Loket implements Runnable{
static int ticketnum =100;
static int count = 0;
int a;
Loket(int a){
this.a = a;
}
public synchronized void run() {

while(ticketnum>0){       
System.out.println("第"+ a+"个售票窗口售出:" +"第"+(++count)+
"张票");
ticketnum --;

   
}

try{
            Thread.sleep(1);
           
        }catch(InterruptedException e){
                e.printStackTrace();
        }

}
}
我设的静态变量ticketnum是100可是最后怎么count会变成104呢,按说应该也是100啊,如果把while换成if就只出来5张票,如果把下面的Thread.sleep()放到while循环中为什么又不到100张了,就是在90多张的地方就停住了。还有加锁到底应该在什么地方加锁啊,我加的synchronized地方对不对啊?菜鸟求大神指导啊

评分

参与人数 1技术分 +1 收起 理由
FFF + 1 鼓励、加油!

查看全部评分

7 个回复

倒序浏览

回帖奖励 +4

你在while循环下面加上一句:
if(count<100)
就行了。
你count并未定义++的上限,所以会出现101 102....这种票。

评分

参与人数 1黑马币 +3 收起 理由
FFF + 3 问题有点太简单~

查看全部评分

回复 使用道具 举报
是这个道理
回复 使用道具 举报
首先.你的synchronized在写run()上
如果成果,应该只有一个线程把所有票卖挖.
但是结果,所有线程都卖出票了,所以synchronize没有成功.
run()方法这样写:
        public void run() {

                while (ticketnum > 0) {
                        synchronized (Loket.class) {
                                if (ticketnum > 0) {
                                        System.out.println("第" + a + "个售票窗口售出:" + "第" + (++count)
                                                        + "张票");
                                        ticketnum--;
                                }
                        }
                }

                try {
                        Thread.sleep(1);

                } catch (InterruptedException e) {
                        e.printStackTrace();
                }

        }
在里面再判断一次是因为可能在
所有线程while (ticketnum > 0)在这判断完可能被抢去执行权.
在没有--之前都在锁前,所以再加次判断.

评分

参与人数 2技术分 +1 黑马币 +3 收起 理由
田磊阳 + 1
FFF + 3 再仔细看看哟~骚年~你回答的不太完善!.

查看全部评分

回复 使用道具 举报
当多条语句在操做同一个现场的共享数据,一个线程对多条语句只执行了一部分,另外一线程参与
执行,造成共享数据的错误。

点评

FFF
骚年,你已经6个技术分了!是时候脱离一句话的水货党了!  发表于 2013-11-22 00:08
回复 使用道具 举报
  1. public class Ticket {

  2.         public static void main(String[] args) {
  3.                 // TODO Auto-generated method stub
  4.                 new Thread(new Window()).start();
  5.                 new Thread(new Window()).start();
  6.                 new Thread(new Window()).start();
  7.                 new Thread(new Window()).start();
  8.                 new Thread(new Window()).start();
  9.                 new Thread(new Window()).start();
  10.                 new Thread(new Window()).start();
  11.                 new Thread(new Window()).start();
  12.         }

  13. }

  14. class Window implements Runnable {
  15.         static int count = 1;
  16.         public void run(){
  17.                 while(count<=10){
  18.                         synchronized(Window.class){
  19.                                 if(count<=10){
  20.                                         System.out.println(Thread.currentThread().getName()+"卖出了第"+count+"张票");
  21.                                         count++;
  22.                                 }
  23.                         }       
  24.                 }
  25.         }
  26. }
复制代码

评分

参与人数 2技术分 +1 黑马币 +6 收起 理由
田磊阳 + 1
FFF + 6 为什么不告诉人家,他在那里错了呢?.

查看全部评分

回复 使用道具 举报
(1)为什么count变成104:
第一你的多线程操作同一份数据用的不是同一把锁,所以当一个线程进入同步代码块等待时,其他线程也可以进入同步代码块,会造成线程安全问题。
因为线程结束的控制条件是ticketnum=0;也就是说只有ticketnum>0的时候,t1,t2,t3,t4,t5才可以进入同步代码块。
所以你的锁应该在while( ticketnum > 0)里面。
如果你这样写:当一个线程进入同步代码块,刚好判断完ticketnum的值为1,此线程挂在这儿。
此时又有新的线程进入同步代码块,判断ticketnum == 1也进入了同步代码块。
这样就是多个线程卖最后一张票,但是只有一张票,所以会出现负数票,count也就大于100了。

(2)while换成if就出来5张票:
因为主线程把t1,t2,t3,t4,t5开启之后,它们各自都卖了一张票,然后t1,t2,t3,t4,t5线程都已经结束了。
因为没有循环去卖剩下的票,if()只是一次判断条件,每个线程都判断一次,然后结束了线程。

(3)Thread.sleep()放在while()中卖不到100张票:
这个你多试几次,其实不是卖不到100张。我试的结果是可以买到90多张,可以买到100张,也可以买到101张。
这都是线程安全出问题造成的。

解决办法:
(1)t1,t2,t3,t4,t5五个线程操作ticketnum这一份数据必须使用同一把锁。
(2)进入同步代码的条件应该放在锁的外面。
具体代码楼上写的很好了,参考一下~~









评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马