zoukankan      html  css  js  c++  java
  • Lock的await/singal 和 Object的wait/notify 的区别

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

    线程consumer 线程producer
    synchronize(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确保阻塞的对象按顺序被唤醒。

    wait()和notify()必须在synchronized的代码块中使用 因为只有在获取当前对象的锁时才能进行这两个操作 否则会报异常 而await()和signal()一般与Lock()配合使用

    notify和notifyAll有什么区别

    notify():唤醒在此对象监视器上等待的单个线程。
    notifyAll():唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

    锁池和等待池

    锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
    等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中
    所以我们可以很容易看到这两者的区别了:

    如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
    当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
    优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
    综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

  • 相关阅读:
    ||和&&
    用jQuery编的一个分页小代码
    Intent携带额外的数据的方法
    Handler消息传递机制
    安卓中的消息提示
    使用AlertDialog创建对话框的大致步骤
    布局管理器
    Android中支持的常用距离单位
    开发自定义View
    Gridview中奇偶数行颜色设置
  • 原文地址:https://www.cnblogs.com/aaron911/p/11043699.html
Copyright © 2011-2022 走看看