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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈洋 中级黑马   /  2013-9-7 22:50  /  1410 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈洋 于 2013-9-10 19:23 编辑

看老毕的视频,其中多线程的生产者和消费者,里面讲解的一个线程等待了,另一个线程就可以进来,多线程不是有锁吗?一个线程都进来了,另一个线程应该进不来啊。。。
  1. 老毕源码
  2. //生产者消费者实例:


  3. class ProducerConsumerDemo
  4. {
  5.         public static void main(String[] args)
  6.         {
  7.                 Resource r = new Resource();

  8.                 Producer pro = new Producer(r);
  9.                 Consumer con = new Consumer(r);

  10.                 Thread t1 = new Thread(pro);
  11.                 Thread t2 = new Thread(pro);
  12.                 Thread t3 = new Thread(con);
  13.                 Thread t4 = new Thread(con);

  14.                 t1.start();
  15.                 t2.start();
  16.                 t3.start();
  17.                 t4.start();

  18.         }
  19. }

  20. /*
  21. 对于多个生产者和消费者。
  22. 为什么要定义while判断标记。
  23. 原因:让被唤醒的线程再一次判断标记。


  24. 为什么定义notifyAll,
  25. 因为需要唤醒对方线程。
  26. 因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

  27. */


  28. class Resource
  29. {
  30.         private String name;
  31.         private int count = 1;
  32.         private boolean flag = false;
  33.                         //  t1    t2
  34.         public synchronized void set(String name)
  35.         {
  36.                 while(flag)
  37.                         try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)
  38.                 this.name = name+"--"+count++;

  39.                 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
  40.                 flag = true;
  41.                 this.notifyAll();
  42.         }


  43.         //  t3   t4  
  44.         public synchronized void out()
  45.         {
  46.                 while(!flag)
  47.                         try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
  48.                 System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
  49.                 flag = false;
  50.                 this.notifyAll();
  51.         }
  52. }

  53. class Producer implements Runnable
  54. {
  55.         private Resource res;

  56.         Producer(Resource res)
  57.         {
  58.                 this.res = res;
  59.         }
  60.         public void run()
  61.         {
  62.                 while(true)
  63.                 {
  64.                         res.set("+商品+");
  65.                 }
  66.         }
  67. }

  68. class Consumer implements Runnable
  69. {
  70.         private Resource res;

  71.         Consumer(Resource res)
  72.         {
  73.                 this.res = res;
  74.         }
  75.         public void run()
  76.         {
  77.                 while(true)
  78.                 {
  79.                         res.out();
  80.                 }
  81.         }
  82. }
复制代码

评分

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

查看全部评分

8 个回复

倒序浏览
在同步中,wait()线程等待之后就会释放执行资格的同时还会释放掉锁,注意这个方法只能用在同步中!
sleep()睡眠是不会释放掉锁的,所以只要它还没醒,执行完同步代码块,其他线程是不会进来的。

评分

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

查看全部评分

回复 使用道具 举报
$love 发表于 2013-9-7 22:57
在同步中,wait()线程等待之后就会释放执行资格的同时还会释放掉锁,注意这个方法只能用在同步中!
sleep()睡 ...

非常感谢,我百度了,没有讲到这个东西的资料,可以告诉我在哪里了解的吗?
回复 使用道具 举报
因为 wait 方法是将当前线程放入了对象的等待集中,所以它只能解除此对象的锁定
这也就能解释为什么一个线程等待了,另一个线程就可以进来。
而sleep方法呢,当前线程不丢失任何监视器(锁)的所属权
比较这两种方法的区别。

评分

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

查看全部评分

回复 使用道具 举报
张文豪 发表于 2013-9-7 23:06
因为 wait 方法是将当前线程放入了对象的等待集中,所以它只能解除此对象的锁定
这也就能解释为什么一个线 ...

{:soso_e100:}谢谢了。
回复 使用道具 举报
线程在wait的时候释放的执行权,也就相当于释放了锁,然后其他线程在获取执行权后就能进来了
回复 使用道具 举报
学习学习!
回复 使用道具 举报
wait()方法必须用在同步当中,sleep()没有硬规定。
wait()当线程运行到wait()会释放锁并等待,一般是被其他线程唤醒才可以继续执行。sleep()是规定的时间到了他自然就继续运行了。
回复 使用道具 举报
楼主,您好!

如果您的问题解决了,请把您问题的未解决更改为已解决

谢谢合作!


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