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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 goldenking56 于 2012-3-4 19:10 编辑

第一个程序没实现同步:
class SaleTickets implements Runnable
{
        int tickets = 100;
        String str = new String("");
        public void run()
        {       
                while(tickets>0)
                {       
                        synchronized(str)
                        {
                               
                                        try
                                        {
                                                Thread.sleep(10);
                                        }
                                        catch(Exception e)
                                        {
                                               
                                        }
                                        System.out.println(new Thread().currentThread().getName()+"剩余票数为 "+tickets--+" 张");
                               
                        }
                }
        }
       

}

class Sale
{
        public static void main(String [] args)
        {
                Runnable r = new SaleTickets();
                Thread t1 = new Thread(r);
                t1.start();
                Thread t2 = new Thread(r);
                t2.start();
                Thread t3 = new Thread(r);
                t3.start();
                Thread t4 = new Thread(r);
                t4.start();
        }
       
}
第二个程序实现了同步:
class SaleTickets implements Runnable
{
        int tickets = 100;
        String str = new String("");
        public void run()
        {       
                while(true)
                {       
                        synchronized(str)
                        {
                                if(tickets>0)
                                {        try
                                        {
                                                Thread.sleep(10);
                                        }
                                        catch(Exception e)
                                        {
                                               
                                        }
                                        System.out.println(new Thread().currentThread().getName()+"剩余票数为 "+tickets--+" 张");
                                }
                        }
                }
        }
       

}

class Sale
{
        public static void main(String [] args)
        {
                Runnable r = new SaleTickets();
                Thread t1 = new Thread(r);
                t1.start();
                Thread t2 = new Thread(r);
                t2.start();
                Thread t3 = new Thread(r);
                t3.start();
                Thread t4 = new Thread(r);
                t4.start();
        }
       
}
这是为什么呀?tickets变量在while()判断与在if()中进行判断不是一样的吗?

评分

参与人数 1技术分 +1 收起 理由
老罗 + 1

查看全部评分

2 个回复

倒序浏览
第一个tickets在 synchronized外面 没有加锁、、、而第二个tickets在synchronized里面、锁住了、、所以就实现同步了、、、、、你再仔细看看tickets的位置。

评分

参与人数 1技术分 +2 收起 理由
老罗 + 2

查看全部评分

回复 使用道具 举报
分析下synchronized方法 :synchronized代码块中的语句只能有一个线程在执行,任意一个对象都有一个标志位,有1和0两种状态当程序执行到synchronized代码块的时候线程会检查对象的标志位是1还是0 ,如果是1则执行程序,同时将对象的标志位设置为0,其他线程执行到synchronized代码块时一看对象标志位为0 ,则线程会阻塞,一直等到对象的标志位为1再执行下面的程序.在上面的程序中一共产生了4个线程,当一个线程执行synchronized代码块的时候其他三个线程会发生阻塞 :第一个线程执行完synchronized代码块后会把对象的标志位设置为1,其他的三个线程中的其中一个会抢到synchronized代码块的执行权,同时会把对象的标志位设置为0,就以这样的顺序循环执行
  我们也可以把对象标志位看成一个监视器,当一个线程执行到synchronized代码块的时候会检查监视器的状态,一个刚执行完synchronized代码块的线程也可以再次检查监视器并执行synchronized代码块
  多个线程要实现同步,必须使用相同的监视器对象(上面程序的4个线程都是用的str同一个对象)如果多个线程使用的不是同一个监视器对象则达不到同步的效果
回复 使用道具 举报
这个不是while和if的问题吧, 第一个程序你要同步的资源tickeet在synhcronized的外面,4个线程启动的时候全部执行了while(ticket>0),,然后有3个等在那,一个去执行下面的代码(为了方便说明,就假设只有一个线程执行了,因为中途有无交换无区别),到最后判定条件不满足的时候,另三个线程还要分别再执行一次,就多了0,-1和-2,这个问题把while(ticket>0)放到synchronized里面就行了

评分

参与人数 1技术分 +2 收起 理由
老罗 + 2

查看全部评分

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