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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄长利 中级黑马   /  2012-3-28 22:56  /  2496 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Ticket implements Runnable
{
        private int ticket = 100;
        Object obj = new Object();
        boolean flag = true;
        public void run()
        {
                if(flag)
                {
                        while(true)
                        {
                                synchronized(obj)
                                {
                                        if(ticket>0)
                                        {
                                                try
                                                {
                                                        Thread.sleep(10);
                                                }
                                                catch (Exception e)
                                                {
                                                }                                       
                                                System.out.println(Thread.currentThread().getName()+"同步代码块卖票"+ticket--);
                                        }
                                }
                        }
                }
                else
                {
                        while(true)
                        {
                                show();
                        }
                }
        }
        public synchronized void show()
        {
               
                        if(ticket>0)
                        {
                                try
                                {
                                        Thread.sleep(10);
                                }
                                catch (Exception e)
                                {
                                }                                       
                                System.out.println(Thread.currentThread().getName()+"构造函数卖票"+ticket--);
                        }
        }
}

class ThisLockDemo
{
        public static void main(String[] args)
        {
                Ticket t = new Ticket();
                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
               
                t1.start();
                try
                {
                        Thread.sleep(10);
                }
                catch (Exception e)
                {

                }
                t.flag = false;
                t2.start();

        }
}

此代码验证同步函数的锁是 this 时,当将 if 语句内的锁设为 obj 对象时,最后的运行结果出现票号为 0 的的时候,是在哪里出现了切换,导致没能实现同步,有些晕了,希望大家给小弟解释一下,谢谢了。。。

4 个回复

正序浏览
两个线程操作一个资源,要想无错误出现,必须使用同一把锁,你用了两个,一个当前对象this,一个是obj!!所以设置obj锁时候出现错误!而且这个代码不好验证同步函数锁是this,用这个:
class Ticket implements Runnable
{
        private int ticket = 100;
        Object obj = new Object();
        boolean flag = true;
        public void run()
        {
               
                        while(true)
                        {
                                show();
                        }
               
        }
        public synchronized void show()
        {
               
                        if(ticket>0)
                        {
                                try
                                {
                                        Thread.sleep(10);
                                }
                                catch (Exception e)
                                {
                                }                                       
                                System.out.println((Thread.currentThread()==this)+"构造函数卖票"+ticket--);
                        }
        }
}

class ThisLockDemo
{
        public static void main(String[] args)
        {
                Ticket t = new Ticket();
                Thread t1 = new Thread(t);
               
               
                t1.start();
               

        }
}
当打印出“true同步函数售票,ticket--”时就证明了同步函数锁是this
回复 使用道具 举报
因为你的show函数持有的锁是当前对象,而你前面的代码中 synchronized(obj),这里的锁是obj,用了不同的锁,所以无法实现同步
回复 使用道具 举报
class Ticket implements Runnable
{
        private int ticket = 100;
        Object obj = new Object();
        boolean flag = true;
        public void run()
        {
                if(flag)
                {
                        while(true)
                        {
                                synchronized(obj)
                                {
                                        if(ticket>0)
                                        {
                                                try
                                                {
                                                        Thread.sleep(10);
                                                }
                                                catch (Exception e)
                                                {
                                                }                                       
                                                System.out.println(Thread.currentThread().getName()+"同步代码块卖票"+ticket--);
                                        }
                                }
                        }
                }
                else
                {
                        while(true)
                        {
                                show();
                        }
                }
        }
        public  void show()
        {
               
                        if(ticket>0)
                        {
                                try
                                {
                                        Thread.sleep(10);
                                }
                                catch (Exception e)
                                {
                                }                                       
                                System.out.println(Thread.currentThread().getName()+"构造函数卖票"+ticket--);
                        }
        }
}

class ThisLockDemo
{
        public static void main(String[] args)
        {
                Ticket t = new Ticket();
                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
               
                t1.start();
                try
                {
                        Thread.sleep(10);
                }
                catch (Exception e)
                {

                }
                t.flag = false;
                t2.start();

        }
}


你只要把show里面的锁去掉就行,因为你前面在调用show的时候已经同步了,如果你在后面再同步一次。那么就直接跑0了~~
回复 使用道具 举报
两个进程相互修改private int ticket = 100;线程A减减时B也减减
导致出现了0当然都在 if(ticket>0)这里时
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马