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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 姬光普 中级黑马   /  2015-5-20 17:43  /  721 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

按视频上多线程部分的一个关于售票的例子
代码:
  1. public class Test4_6{

  2.         /**
  3.          * 简单的多线程卖票程序,证明继承Thread类这种方法不合适
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 Tickets t=new Tickets();
  8.                
  9.                 Thread t1=new Thread(t);
  10.                 Thread t2=new Thread(t);
  11.                 Thread t3=new Thread(t);
  12.                 Thread t4=new Thread(t);
  13.                 t1.start();
  14.                 t2.start();
  15.                 t3.start();
  16.                 t4.start();

  17.                
  18.         }

  19. }
  20. class Tickets implements Runnable{
  21.         private static int num=100;//总共100张票,所有窗口共同卖,所以用静态
  22.        
  23.         public void run(){
  24.                 while(num>0){
  25.                                 System.out.println(Thread.currentThread().getName()+"----卖出----第"+num+"张票");
  26.                                 num--;
  27.                 }
  28.         }
  29. }
复制代码
运行的结果前几行是:
  1. Thread-1----卖出----第100张票
  2. Thread-2----卖出----第100张票
  3. Thread-0----卖出----第100张票
  4. Thread-2----卖出----第98张票
  5. Thread-3----卖出----第99张票
  6. Thread-1----卖出----第99张票
  7. Thread-3----卖出----第95张票
  8. Thread-3----卖出----第93张票
  9. Thread-2----卖出----第96张票
  10. Thread-0----卖出----第97张票
  11. Thread-2----卖出----第91张票
  12. Thread-3----卖出----第92张票
复制代码
到后面就正常了,我想问一下是不是因为处理器是多核的原因啊?????
这块真心不熟,求指教

13 个回复

倒序浏览
这个需要给各个线程加同一个锁的。
这种情况发生,可能是Thread-1拿到执行权,执行到输出语句后,还没有执行num--的时候,Thread-2拿到CPU执行权,然后也是同样的问题,Thread-0拿到。就出现了开头的三个100号票。
后面理论上也可能出现这种情况。

同步  可以解决这种多线程的安全问题。
回复 使用道具 举报
不是处理器多核的问题,因为你没有加锁,导致线程不同步,while代码块内会出现几个线程同时满足条件打印后面的num值,导致重复,最后应该还可能会出现负数票,你可以参考下我之前写的代码:
package com.ceshi;

class Test implements Runnable
{
        private int tick = 100;
        Object obj = new Object();
        public void run()
        {
                while(tick > 0)
                {
                        synchronized(obj)
                        {
                                if(tick > 0)
                                {
                                        try
                                        {
                                                Thread.sleep(10);
                                        }
                                        catch(Exception e)
                                        {

                                        }
                                        System.out.println(Thread.currentThread().getName()+"...sale..."+tick--);
                                }
                        }
                }
        }
}

public class TicketDemo
{
        public static void main(String[] args)
        {
                Test t = new Test();
                Thread d1 = new Thread(t);
                Thread d2 = new Thread(t);
                Thread d3 = new Thread(t);
                Thread d4 = new Thread(t);
                d1.start();
                d2.start();
                d3.start();
                d4.start();
        }
}
回复 使用道具 举报
小悟空et 发表于 2015-5-20 18:45
这个需要给各个线程加同一个锁的。
这种情况发生,可能是Thread-1拿到执行权,执行到输出语句后,还没有执 ...

学到了,谢谢
回复 使用道具 举报
wangaz 发表于 2015-5-20 19:12
不是处理器多核的问题,因为你没有加锁,导致线程不同步,while代码块内会出现几个线程同时满足条件打印后 ...

我试了,你的代码可以的,但是视频上老师的代码也没有加锁,为什么没有出现这种情况呢
回复 使用道具 举报
那可能是老师演示的时候运气好,这种多线程的情况本身每次运行的显示都不太一样,只要确保结果正确就欧啦。
回复 使用道具 举报 1 0
问题出在28行与29行
回复 使用道具 举报
当t1执行完第28行还未执行第29行时,cpu执行权被t2抢去了,这时num--还未执行,t2打印出的就与t1相同,同理就能明白t3、t4为什么也是100。
回复 使用道具 举报 1 0
zq19910303 发表于 2015-5-21 07:26
当t1执行完第28行还未执行第29行时,cpu执行权被t2抢去了,这时num--还未执行,t2打印出的就与t1相同,同理 ...

对的,我试过了,将28和29行合起来,虽然有安全隐患,但是至少不会出现4个100,谢谢你了
回复 使用道具 举报
前面也有个孩子问这个问题了 ,吧输出语句和 num-- 合并为一行就可以了  输出 num--
回复 使用道具 举报
线程不安全,多个线程访问了一个数据
回复 使用道具 举报
没给多线程加锁
回复 使用道具 举报
膜拜大神!都非常厉害!
回复 使用道具 举报
多线程比单线程安全
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马