synchronized 无论放哪里,只有一个Locket会执行动作,其它等待,实际上不会执行

解决方案 »

  1.   

    http://bbs.csdn.net/topics/390645360 和这个贴是同一个人吗? 那你看看那贴的回复
      

  2.   

    你的问题归根结底还是没达到同步的效果。
    1.第一个问题,为什么到104呢?因为线程睡眠在外面,都是while运算基本上不可能有sleep的执行后的效果,所以在外面的话写不写都是一个样,出现104就是因为进程之间的值可以随时改变,static值可以有任何线程来更改,所以会出现104,而且你会发现同一张票会出现好几次。
    2.为啥会小于100呢,其实sleep写在里面,无形中给各个线程相互执行增加了容错机制,不至于各个线程一直再竞争,从而近乎合理的运算,其他也有一两个相同的票出现,也会出现100,101等数字,但近乎合理,如果把时间放大就更接近了
    3换成if之后每个线程就执行了一次,毋庸置疑的,不会多余五次的,正确的理解应该是每个线程共享一个变量ticketnum ,使他不至于小于0而且各个线程执行后的效果还得正确,楼主的代码没有考虑到同步只是正对同一个对象,而你已经在堆里生成了5个new对象了。如果不是同一个对象那就要同步一个共有的栈里的东西,如调用类里的static变量或是类,当然不建议用类作为同步对象,在真实的系统中如果将类“锁”住,可能会导致其他业务访问这个类。楼主修改代码修改如下,
    public class TimerContent { static String ss="";
    public static void main(String args[]) throws Exception{
    Tc t1=new Tc(1);
    Tc t2=new Tc(2);
    Tc t3=new Tc(3);
    Tc t4=new Tc(4);
    Tc t5=new Tc(5);

    Thread th1=new Thread(t1);
    Thread th2=new Thread(t2);
    Thread th3=new Thread(t3);
    Thread th4=new Thread(t4);
    Thread th5=new Thread(t5);

    th1.start();
    th2.start();
    th3.start();
    th4.start();
    th5.start();
    }
        
    }class Tc implements java.lang.Runnable{
    static int pp=100;
    static int count=0;
    private int aa;
    public Tc(int aa){
    this.aa=aa;
    }
    public void run(){
    while(pp>0){
        synchronized(TimerContent.ss){
            if(pp>0){
     count++;
     System.out.println("第"+aa+"个窗口,第"+count+"张票"+", "+pp);
     pp--;
            }
         }
        try{
    Thread.sleep(1);
        }catch(Exception e){
    e.printStackTrace();
        }
    }

    }
    },当然上面也可以不用同步,将TimerContent.ss也可以改为自定的变量,执行前执行后的值变化一下
      

  3.   

    可是我的静态变量设成100啊,每次在while循环的时候不是都会减小一次么?到0就不能再进行循环了,那不就是总共100次么?相当于100 张票。还有楼主的代码没有考虑到同步只是正对同一个对象,而你已经在堆里生成了5个new对象了。你说的这句,我不理解啊,我要模拟5个售票窗口那new5个窗口对象不对吗?那应该怎么理解呢?题就是要模拟5个售票窗口售出100张票,并且打印票的号
      

  4.   

    再补一句啊,如果把sleep放的里面再把sleep的时间调长了,那我做的算符合题意吗?感觉线程好难理解啊,麻烦你啦
      

  5.   

    直接回复你所有的问题,五个new对象,所以你原来的synchronized不起任何作用,原来的synchronized范围只是你的单个的new出来的对象,五个线程可以任意竞争,无顺序可言,所以要找一个对象或对象静态成员属性作为锁。至于你说的为什么“到0就不能再进行循环了,那不就是总共100次么?”,有没有考虑到每个类对象都是有事务的概念,不是只是允许一个对象来调,n个对象都可以调用这个方法,没有时间可言,没有顺序可言,所以完全有可能多个对象同时执行run方法,同时修改ticketnum 的值,比如说道100的时候完全可以四五个线程同事执行这个方法,当执行到--的时候大家都--,这就是出现了几个重复的票号,也有可能同时到100了,第一个先--了,后面的挨个--,就会出现大于100的情况。你的问题“你写的那个锁我也不明白锁到底应该加在什么地方啊?”根据你上面的代码,锁加载run方法上肯定不行的,因为这个run方法是实现的方法,无法更改其方法参数,必须在方法内部加锁已达到锁的目的,当然其他非线程业务加到方法是可以的,根据业务实现来确定锁加在哪。最后一个问题,“sleep时间加长”完全可以,不过线程参与量会变少,不是五个,随着时间加长,最后有可能只有一个线程参与,如果是现实中的买票,建议时间不要太长,意思一下就行了,才能观察到线程竞争的效果