wait 和notify的应用场景
在学习wait,notify之前首先需要解释java中wait()和notify()的应用场景。wait和notify提供了对多个线程之间的等待和通知操作。例如抓取站外多张图片通常会通过多个thread同时进行,但主线程需要等到这批数据返回的结果。
多线程操作通常都有提交者(submiter)和执行者(executor),java通过concurrent包提供的Executors提供了很好的支持,如果不通过wait和notify,只能通过轮循来实现,实际上是很低效的:
看看之前我们网站的fetch实现方式:
def fetch(self, url): for i in range(2): title, images = build_fetch(url).fetch(url) if images: break if images: images = images[:150] self._finished = False self._total = len(images) current = 0 while current < self._total: self.pool.queueTask(self.check_image, images[current:current + self._per_check], self.collect_image) current = current + self._per_check from time import sleep # 等待抓取完毕 while not self._finished: sleep(0.05) pass return title, self._urls
java
首先可以这样理解,每个object实际上自身和一个monitor(锁)关联,object.wait(timeout) :使当前线程放弃object的锁并等待,除非其它线程调用了object.notify()或者object.notifyAll(),或者使等待线程中断,或者等待了timeout时间。
object.notify():随机唤醒一个等待在object的线程 ,该线程和其他活动线程一起争夺object的锁。
object.notifyAll():唤醒所有等待在object的线程 ,线程和其他活动线程一起争夺object的锁。
根据 java api doc ,使用wait,notify注意事项:
1. 调用线程必须已经获得了object的锁,即在synchronized方法或者synchronized(object){}语句块中调用。
2. 调用线程被唤醒后实际上并不会立即执行后续操作,它要先和其它活动线程竞争获得当前对象的锁,得到对象锁后才能接着执行wait后代码。
下面是一个例子:
public class Tester3 { public synchronized void take() { System.out.println("take"); try { Thread.currentThread().sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void put() { System.out.println("put"); } /** * @param args */ public static void main(String[] args) { final Tester3 tester = new Tester3(); Thread t = new Thread(new Runnable() { @Override public void run() { System.out.println("take begin"); tester.take(); System.out.println("take end"); } }); t.start(); t = new Thread(new Runnable() { @Override public void run() { System.out.println("put begin"); tester.put(); System.out.println("put end"); } }); t.start(); } }
输出(put必须等到get释放锁之后才能被执行):
take begin
put begin
take
take end
put
put end
python
python对象没有隐式的和一个锁关联,且python中的 wait,notify是由python语言自身利用锁(Lock)实现,实现类为Condition,但是概念思想上是和java保留一致,如果要模拟 java的话,只需创建python对象时,显式将一个Condition实例赋给创建对象的一个成员属性,那么可以对应java中的doc来看一下 python的实现:
threading.py Condition类:
1。wait,notify必须在获得当前对象锁的前提下:
def wait(self, timeout=None): if not self._is_owned(): raise RuntimeError("cannot wait on un-aquired lock") ....... def notify(self, n=1): if not self._is_owned(): raise RuntimeError("cannot notify on un-aquired lock") .......
可见在wait,notify时都要进行检查,其中self._is_owned()正是判断调用线程是否获得了Condition的内置锁,也即java中对象monitor的概念。
2.wait调用后会使当前线程放弃已经获得对象锁:
def wait(self, timeout=None): ..... saved_state = self._release_save()
其中 self._release_save正是进行了放弃Condition内置锁的操作,也对应着java先放弃对象monitor的概念
3.wait 使当前线程等待的实现
java doc说明:将当前线程加入object的waitset,然后等待。
python实现为:当前线程在一个新建锁上等待,把该锁加入到condition的等待数组中,线程等待锁的release
def wait(self, timeout=None): ... #新建一把锁 waiter = _allocate_lock() #现获得一次,后面再获得就阻测 waiter.acquire() #记录等待 self.__waiters.append(waiter) ..... if timeout is None: #在该锁上等待 waiter.acquire() if __debug__: self._note("%s.wait(): got it", self)
4.notify唤醒等待线程实现
同java不同,java notify唤醒的线程不能确定,而python则能确定,一定是第一个调用wait的线程被唤醒,即为先进先出的队列结构。
对于python为:release __waiters等待数组的第一个锁,对应的等待线程即可重新开始在wait函数内运行:
def notify(self, n=1): .... waiters = __waiters[:n] for waiter in waiters: #锁释放,意味着等待锁的对应线程可是从wait函数运行 waiter.release() try: __waiters.remove(waiter) except ValueError: pass
5.唤醒线程和其他活动线程争夺对象锁
唤醒线程并不是立刻从wait()返回开始它的实际操作,而是要先争夺conditon的内置锁,即java的object monitor:
def wait(self, timeout=None): #等待在新建锁上 if timeout is None: waiter.acquire() #新建锁释放了,但是要先获得condition内置锁才能返回 self._acquire_restore(saved_state)
6.wait的超时处理与notifyAll 略
实例:
分别用java与python实现了经典的生产者与消费者模型
原文:http://yiminghe.iteye.com/blog/673379
相关推荐
源码—Java多线程5—死锁和wait notify notifyAll
开一个子线程来完成一个循环处理的工作,我在主线程中能灵活控制这个子线程的开始、暂停/继续、结束。
主要介绍了java多线程wait,notify,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面小编和大家一起来学习一下吧
java多线程下wait和notify的作用
使用Java多线程的wait和notify方法实现最简单的生产者消费者模式
java多线程之wait,notify的用法([ 详解+实例 ]).
Java多线程机制 9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 ...
Java多线程的样例代码,工程,内含wait()、notify()和sychronized的使用范例。
python 多线程的同步机制 以python2例程的方式讲解了python 多线程的同步 常用的方法,主要是锁、条件同步、队列 多线程的同步 多线程情况下最常见的问题之一:数据共享; 当多个线程都要去修改某一个共享数据...
Java 同步方式 wait和notify/notifyall
java中多线程编程notify、wait的使用
主线程去控制子线程wait与notify
主要介绍了Java多线程中wait、notify、notifyAll使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify 和 notifyAll 来实现...
主要介绍了Java多线程通讯之wait,notify的区别详解,非常不错,具有一定的参考借鉴借鉴价值,需要的朋友可以参考下
Java多线程同步(wait()notify()notifyAll())[文].pdf
《JAVA多线程设计模式》PDF 下载 《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口...
wait和notify讲解
一个理解wait()与notify()的例子,让你更好理解.