使用Lock来实现生产者和消费者问题

来源:互联网 发布:小米手环2 详细数据 编辑:程序博客网 时间:2024/05/10 19:55

Lock的await/singal 和 Object的wait/notify 的区别

在使用Lock之前,我们都使用Object 的wait和notify实现同步的。举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒。

线程consumer线程producersynchronize(obj){
    obj.wait();//没东西了,等待
}synchronize(obj){
    obj.notify();//有东西了,唤醒
}

有了lock后,世道变了,现在是:

lock.lock();
condition.await();
lock.unlock();lock.lock();
condition.signal();
lock.unlock();

为了突出区别,省略了若干细节。区别有三点:

  1. 1. lock不再用synchronize把同步代码包装起来;
  2. 2. 阻塞需要另外一个对象condition;
  3. 3. 同步和唤醒的对象是condition而不是lock,对应的方法是await和signal,而不是wait和notify。

为什么需要使用condition呢?简单一句话,lock更灵活。以前的方式只能有一个等待队列,在实际应用时可能需要多个,比如读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),等待队列负责保存被阻塞的线程(condition完成)。

通过查看ReentrantLock的源代码发现,condition其实是等待队列的一个管理者,condition确保阻塞的对象按顺序被唤醒。

在Lock的实现中,LockSupport被用来实现线程状态的改变,后续将更进一步研究LockSupport的实现机制。


  package com.thread;    import java.util.LinkedList;  import java.util.concurrent.locks.Condition;  import java.util.concurrent.locks.Lock;  import java.util.concurrent.locks.ReentrantLock;      /**   * 使用Lock来实现生产者和消费者问题   *    *    *   */  public class ProducerConsumer {      public static void main(String[] args) {          Basket b = new Basket();          Product p = new Product(b);          Consumer c = new Consumer(b);          Consumer c1 = new Consumer(b);          new Thread(p).start();          new Thread(c).start();          new Thread(c1).start();      }  }  //馒头  class ManTou{      int id;      public ManTou(int id) {          this.id = id;      }      @Override      public String toString() {          return "ManTou"+id;      }  }    //装馒头的篮子  class Basket{      int max = 6;      LinkedList<ManTou> manTous = new LinkedList<ManTou>();      Lock lock = new ReentrantLock(); //锁对象      Condition full = lock.newCondition();  //用来监控篮子是否满的Condition实例      Condition empty = lock.newCondition(); //用来监控篮子是否空的Condition实例      //往篮子里面放馒头      public void push(ManTou m){          lock.lock();          try {              while(max == manTous.size()){                  System.out.println("篮子是满的,待会儿再生产...");                  full.await();              }              manTous.add(m);              empty.signal();          } catch (InterruptedException e) {              e.printStackTrace();          }finally{              lock.unlock();          }      }      //往篮子里面取馒头      public ManTou pop(){          ManTou m = null;          lock.lock();          try {              while(manTous.size() == 0){                  System.out.println("篮子是空的,待会儿再吃...");                  empty.await();              }              m = manTous.removeFirst();              full.signal();          } catch (InterruptedException e) {              e.printStackTrace();          }finally{              lock.unlock();              return m;          }      }  }  //生产者  class Product implements Runnable{      Basket basket;      public Product(Basket basket) {          this.basket = basket;      }      public void run() {          for (int i = 0; i < 40; i++) {              ManTou m = new ManTou(i);              basket.push(m);              System.out.println("生产了"+m);              try {                  Thread.sleep((int)(Math.random()*2000));              } catch (InterruptedException e) {                  e.printStackTrace();              }                        }      }  }  //消费者 class Consumer implements Runnable{     Basket basket;     public Consumer(Basket basket) {         this.basket = basket;     }     public void run() {         for (int i = 0; i < 20; i++) {             try {                 Thread.sleep((int)(Math.random()*2000));             } catch (InterruptedException e) {                 e.printStackTrace();             }             ManTou m = basket.pop();             System.out.println("消费了"+m);         }     } }


0 0
原创粉丝点击