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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 孙天 黑马帝   /  2012-4-14 11:25  /  1753 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

为什么本方必须唤醒对方才有效,或者干脆唤醒全部,本方会被判断是否继续等待?
class Resource
{
        private String name;
        private int count;
        private boolean flag;
        public synchronized void set(String name)//
        {
                while(flag)
                        try{this.wait();}catch(Exception e){}//  (活)  t1 (活)t0
                this.name = name+count;   
                count++;

                System.out.println(Thread.currentThread().getName()+"....生产者..."+this.name);//生产者 商品0 生产者 商品1 商品2

                flag = true;
                notifyAll();
        }

        public synchronized void out()//
        {
                while(!flag)
                        try{this.wait();}catch(Exception e){}//t2 t3
                System.out.println(Thread.currentThread().getName()+"......消费者......."+this.name);//消费 商品0
                flag = false;
                notifyAll();
        }

}


class Producer implements Runnable
{
        private Resource r;
        Producer(Resource r)
        {
                this.r = r;       
        }
        public void run()
        {
                while(true)
                {
                        r.set("商品");
                }
        }
}

class Consumer implements Runnable
{
        private Resource r;
        Consumer(Resource r)
        {
                this.r = r;
        }
        public void run()
        {
                while(true)
                {
                        r.out();
                }
        }
}


class ProConDemo
{
        public static void main(String[] args)
        {
                Resource r = new Resource();
                Producer pro = new Producer(r);
                Consumer con = new Consumer(r);
                Thread t0 = new Thread(pro);
                Thread t1 = new Thread(pro);
                Thread t2 = new Thread(con);
                Thread t3 = new Thread(con);
                t0.start();
                t1.start();
                t2.start();
                t3.start();

        }
}

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

5 个回复

倒序浏览
这个三言两句说不清楚,多看几遍视频吧~
回复 使用道具 举报
在生产者和消费者的同步问题中,生产者生产一个产品,消费者就应该消费一个产品。其中是具有一一对应的关系的。
也就是说生产者生产一个产品以后就应该进入等待状态,等待消费者将产品消费掉。
此时消费者就应该进入等待状态,并唤醒生产者,继续等待生产者生产产品。

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
因为当本方线程执行完并改变标志位后只有对方才能改变flag标识。在唤醒本方后,由于标识位已经被本方的线程改变,所以即使被唤醒也会因为判断标识位而重新wait,若对方线程都是wait状态而没有被唤醒那就会导致死锁。

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报

以上面的为例,如果不是notifyAll(),而是notify(),
程序一开始,标记flag默认值为false,t1线程运行完毕之前,会通过"flag = true;"改变flag标记的值,改变后的值为true,
t1线程同过while(true)循环重新运行时,读到flag为true是,会执行while循环中的语句,读取wait(),t1线程进入冻结状态.
t2线程开运行,读到flag为true是,会执行while循环中的语句,读取wait(),t2线程进入冻结状态,
这个时候t3线程就会开始运行,同t1线程运行一样,t3第一次执行完毕前,会通过flag = false;改变flag标记,
使t3线程进入冻结状态,
进而使t4线程进入冻结状态,

这样程序就会出现t1,t2,t3,t4都处于冻结状态的状况.


评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
为什么本方必须唤醒对方才有效,或者干脆唤醒全部,本方会被判断是否继续等待?

唤醒自己方也行,但是,生产两个只卖了一个(而且count错误,因为count计一次数的时候理应生产一个卖一个,否则会count2次跳过了卖),不符合实际。
还有一种就是,唤醒后一个(不是all)有可能唤醒的本方而标记更改,本方等待,对方也再等待(因为没唤醒)。

如果换成了lock和condition 就变成一对多 ,就能指定唤醒对方。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马