黑马程序员技术交流社区

标题: 关于 synchronized 和 wait 的问题 [打印本页]

作者: heheka123    时间: 2014-4-20 13:21
标题: 关于 synchronized 和 wait 的问题
本帖最后由 heheka123 于 2014-4-21 19:59 编辑

先看这个段代码,是老师讲生产者消费者的时候的
  1.         public synchronized void set(String name){
  2.                 while(flag){
  3.                         try{wait();}catch(Exception e){}
  4.                 }
  5.                 this.name=name+"--"+count++;
  6.                 System.out.println(Thread.currentThread().getName()+"....生产者..."+this.name);
  7.                 flag=true;
  8.                 this.notifyAll();
  9.         }
复制代码

这个方法上有个  synchronized  意思就是 当有第二个线程是进不来的, 那里面的wait() 还有什么用呢,让谁等待啊?
作者: 呆呆沙师妹    时间: 2014-4-20 13:28
区别一下sleep()和wait()。
sleep():让出CUP执行权,不释放同步锁;
wait():不仅让出CUP执行权,并且释放同步锁。
当持有锁的线程进入等待状态,同步锁被释放,别的进程就能进来了。
作者: 清风有意    时间: 2014-4-20 13:29
在方法上的synchronized锁是的对象是本类对象即synchronized(this),这里的生产者和消费者是两个不同的类,所以不是同一个锁,这里加锁是为了同步
作者: 忘川    时间: 2014-4-20 13:34
  1. /*
  2. 多线程中最为常见的应用案例:
  3. 生产者消费者问题。
  4. 生产和消费同时执行,需要多线程。
  5. 但是执行的任务却不相同,处理的资源确实相同的:线程间的通信。

  6. 1,描述一下资源。
  7. 2,描述生产者,因为具备着自己的任务。
  8. 3,描述消费者,因为具备着自己的任务。


  9. 问题1:数据错误:已经被生产很早期的商品,才被消费到。
  10. 出现线程安全问题,加入了同步解决。使用同步函数。
  11. 问题已解决:不会在消费到之前很早期的商品。

  12. 问题2:发现了连续生产却没有消费,同时对同一个商品进行多次消费。
  13. 希望的结果应该是生产一个商品,就被消费掉。生产下一个商品。
  14. 搞清楚几个问题?
  15. 生产者什么时候生产呢?消费者什么时候应该消费呢?
  16. 当盘子中没有面包时,就生产,如果有了面包,就不要生产。
  17. 当盘子中已有面包时,就消费,如果没有面包,就不要消费。

  18. 生产者生产了商品后应该告诉消费者来消费。这时的生产者应该处于等待状态。
  19. 消费者消费了商品后,应该告诉生产者,这时消费者处于等待状态。

  20. 等待:wait();
  21. 告诉:notify();//唤醒

  22. 问题解决:实现生产一个消费一个。

  23. =====================
  24. 等待/唤醒机制。
  25. wait(): 会让线程处于等待状态,其实就是将线程临时存储到了线程池中。
  26. notify():会唤醒线程池中任意一个等待的线程。
  27. notifyAll():会唤醒线程池中所有的等待线程。

  28. 记住:这些方法必须使用在同步中,因为必须要标识wait,notify等方法所属的锁。
  29. 同一个锁上的notify,只能唤醒该锁上的被wait的线程。

  30. 为什么这些方法定义在Object类中呢?
  31. 因为这些方法必须标识所属的锁,而锁可以是任意对象,任意对象可以调用的方法必然时Object类中的方法。

  32. 举例:小朋友抓人游戏。



  33. */

  34. //1,描述资源。属性:商品名称和编号,  行为:对商品名称赋值,获取商品。
  35. class Resource
  36. {
  37.         private String name;
  38.         private int count = 1;

  39.         //定义标记。
  40.         private boolean flag = false;
  41.        
  42.         //1,提供设置的方法。
  43.         public synchronized void set(String name)
  44.         {

  45.                 if(flag)
  46.                         try{this.wait();}catch(InterruptedException e){}
  47.                 //给成员变量赋值并加上编号。
  48.                 this.name = name + count;
  49.                 //编号自增。
  50.                 count++;
  51.                 //打印生产了哪个商品。
  52.                 System.out.println(Thread.currentThread().getName()+"......生产者...."+this.name);

  53.                 //将标记改为true。
  54.                 flag = true;
  55.                 //唤醒消费者。
  56.                 this.notify();
  57.         }
  58.         public synchronized void out()
  59.         {
  60.                 if(!flag)
  61.                         try{this.wait();}catch(InterruptedException e){}
  62.                 System.out.println(Thread.currentThread().getName()+"....消费者...."+this.name);
  63.                 //将标记该为false。
  64.                 flag = false;
  65.                 //唤醒生产者。
  66.                 this.notify();
  67.         }
  68. }

  69. //2,描述生产者。
  70. class Producer implements Runnable
  71. {
  72.         private Resource r ;
  73.         // 生产者一初始化就要有资源,需要将资源传递到构造函数中。
  74.         Producer(Resource r)
  75.         {
  76.                 this.r = r;
  77.         }
  78.         public void run()
  79.         {
  80.                 while(true)
  81.                 {
  82.                         r.set("面包");
  83.                 }
  84.         }
  85. }

  86. //3,描述消费者。
  87. class Consumer implements Runnable
  88. {
  89.         private Resource r ;
  90.         // 消费者一初始化就要有资源,需要将资源传递到构造函数中。
  91.         Consumer(Resource r)
  92.         {
  93.                 this.r = r;
  94.         }
  95.         public void run()
  96.         {
  97.                 while(true)
  98.                 {
  99.                         r.out();
  100.                 }
  101.         }
  102. }




  103. class ThreadDemo9
  104. {
  105.         public static void main(String[] args)
  106.         {
  107.                 //1,创建资源对象。
  108.                 Resource r = new Resource();

  109.                 //2,创建线程任务。
  110.                 Producer pro = new Producer(r);
  111.                 Consumer con = new Consumer(r);

  112.                 //3,创建线程。
  113.                 Thread t1 = new Thread(pro);
  114.                 Thread t2 = new Thread(con);

  115.                 t1.start();
  116.                 t2.start();
  117.         }
  118. }
复制代码

你没看全啊,这是毕姥爷讲课的笔记,你看下,wait()是让当前这个线程进入等待
作者: 清风夜独醉    时间: 2014-4-20 14:11
首先你要明白wait()方法的作用:
wait()方法,线程会停止运行,不会自动启动,要等其它线程唤醒。然后该线程不但交出CPU执行权,并且还释放锁,也就是说该线程不再持有锁,其它线程可以进来。
另外你要与sleep()方法区别开,别混淆了。
sleep()方法,线程会暂时停止运行,并交出CPU执行权,等睡眠时间到了线程会继续启动,但是这个过程并不释放锁,也就是说该线程仍然持有锁,其它线程进不来。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2