当前位置: 首页 > Thinking in Java > 正文

第21章 – 并发 – 线程之间的协作 object的wait()与notify()和notifyAll()

线程之间的协作 object的wait()与notify()和notifyAll()

 

1. 这些方法只能在 同步控制方法(synchronized修饰的方法)或同步块(synchronized修饰代码块)

 

   中调用. 非同步方法或非同步块中调用,代码可以编译通过,但执行时抛IllegalMonitorStateException

 

   因为调用这些对象时,必须要事先获取对象的锁.

 

2. 调用wait()之后,立刻释放锁, 当前线程挂起(就相当于CPU暂时不管这个线程,不分配这个线程执行时间了)

 

   当前现场挂起后,等待notify()或notifyAll()发信号,一旦等到了信号,就重新唤醒(相当于CPU又开始管这个线程了)

 

   因为wait()是在synchronized中,所以wait()之后再次被唤醒的,还需要争抢锁.如果没有抢到锁,一般还是要继续

 

   挂起的,所以wait()一般需要放到while(感兴趣的条件)这样的循环中的.

 

3. 调用 notify()或 notifyAll() 只是给wait()的线程发信号,唤醒一个线程. 但是notify()或 notifyAll()并不释放锁.

 

   只有在用synchronized 包裹的的代码(包含 notify()或 notifyAll() )全部执行完之后,才释放锁.释放锁之后,被唤醒

 

   的线程有一个能抢到锁,然后继续执行wait()之后的代码.

 

4. 错失的信号(p706)

 

   T1:

   synchronized(sharedMonitor)

   {

   <setup condition for T2> //将someCondition变成false

   sharedMonitor.notify();

   }

 

   T2:

   while(someCondition)

   {

   //Point1

   synchronized(sharedMonitor)

   {

   sharedMonitor.wait();

   }

   }

 

   上述有问题的写法,发生问题的场景 

   (1)前提是: T2尚未调用wait(),初始someCondition为true

   (2)产生的问题是:T2不能按预期正常工作,导致T2无限期wait(),目的是someCondition为false时,T2唤醒(离开wait())

   (3)问题分析:假设某一时刻,T2开始执行,并且someCondition为true,导致执行到Point1处,此时线程

      调度器可能切换到T1的<setup condition for T2>时将someCondition设置为false,然后调用notify()后,

      调度器再次切换到T2的Point1之后,此时实际上someCondition为false了,而T2中已经来不及了,继续执行

      sharedMonitor.wait();导致T2无限期执行下去(因为T1的notify只执行一次).

   (4)问题修改:使用下面的代码替换T2

      synchronized(sharedMonitor)

      {

      while(someCondition)

      {

      sharedMonitor.wait();

      }

      }

      修改后,假如T1首先执行,则执行后将someCondition改成false,当执行T2时并不会进入wait().

      假如T2首先执行,则因为初始someCondition为true,T2进入wait(),然后T1开始执行,T1中notify

      后,T2被再次唤醒,再次执行while后,不会wait了(以为T1中将someCondition设置为false)

 

5. notifyAll()因为某个特定的锁而被调用时,只有等待这个锁的任务才会被唤醒,并不是唤醒所有等待的线程.(p707)

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2148.html | 边城网事

该日志由 边城网事 于2015年03月18日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第21章 – 并发 – 线程之间的协作 object的wait()与notify()和notifyAll() | 边城网事
关键字: ,

第21章 – 并发 – 线程之间的协作 object的wait()与notify()和notifyAll() 暂无评论

发表评论

快捷键:Ctrl+Enter