黑马程序员技术交流社区

标题: 线程卖票的为什么会出错 [打印本页]

作者: 王雷1    时间: 2013-11-20 16:02
标题: 线程卖票的为什么会出错
本帖最后由 王雷1 于 2013-11-21 10:22 编辑

为什么只能用while循环,for循环就出错,还是 我写的有毛病


class chezan implements Runnable
{
        int piao=100;
        int sum;
        public void add(int x)
        {
                sum=sum+x;
                System.out.println(sum);
        }
        public void run()
        {
                                
                for(this.piao=100;this.piao>0;this.piao--)
                        {
                                synchronized(this)
                                {
                                        System.out.println(Thread.currentThread().getName()+"火车票"+piao);
                                        add(1);
                                }
                        }
               
        }
}
class ti//正好是103张,好几次都是这个结果
{//如果不是正好的103张我还能理解为线程,但是好几次都是103张
        public static void main(String[] args)
        {
                chezan t=new chezan();
               
                Thread x1=new Thread(t);
                Thread x2=new Thread(t);
                Thread x3=new Thread(t);
                Thread x4=new Thread(t);
                x1.start();
                x2.start();
                x3.start();
                x4.start();
        }
}
//只是循环不同,为什么效果是不一样的

作者: ″先森丶玹°    时间: 2013-11-20 16:31
for循环只是判断是否超出100张票的情况,而同步中synchronized(this),并没有判断是否会有负票的情况 只要加上一句话就Ok了。
synchronized(this)
{
         if(piao>0){
           System.out.println(Thread.currentThread().getName()+"火车票"+piao);
                                        add(1);
         }
   }
作者: hurryup    时间: 2013-11-20 16:51
既然用了对象锁,就要使用等待唤醒的机制了,怎么还继承thread类呢,没看懂。
作者: @ne_pie尒ce    时间: 2013-11-20 16:54
for(this.piao=100;this.piao>0;this.piao--)
for()参数列表中有对共享数据的操作this.piao--,而你没有把他放进同步代码块中
自然会出现卖出负数票的情况,线程是不安全的。
而把对共享数据的操作放进同步代码块中
synchronized(this)
            {   
                for(this.piao=100;this.piao>0;this.piao--)
                        {
                                        synchronized(this)
                                    {
                                        System.out.println(Thread.currentThread().getName()+"火车票"+piao);
                                        add(1);
                                }
                        }
            }
这样每个线程都会有100张票,也是不符合需求的。
因此还是有while循环操作比较好。
作者: 黄炳期    时间: 2013-11-20 17:39
每一个回答都是一个提示。
如果问题已经解决,请及时修改主题为“提问结束”。
修改主题的方法链接
http://bbs.itheima.com/thread-89313-1-1.html
作者: smileven    时间: 2013-11-20 19:19
(1)     for(this.piao=100;this.piao>0;this.piao--)
           {synchronized(this); }
这种方法对票的数量判断是在synchronized同步代码块的外面。
当票已经卖完,但是如果有线程已经经过了for语句中piao>0的判断,那么肯定会出现负数票。

(2)      while(true)
              synchronized(this)
                   {if(piao > 0)
                              }

这种方法是将票的数量的判断放在synchronized同步代码跨里面,
虽然有线程进入同步代码块中等待,但是piao的值为0的话,就不会往下执行同步代码块。
所以这样线程是俺去滴~~






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