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

python wait notify_java与python多线程wait,notify操作比较相关推荐

  1. python多线程处理数据库_在flask框架下利用Python的threading或thread多线程库如何操作数据库?...

    萌新在写网站的发送邮件验证,为了防止用户滥发,所以加了权限.前端简单地disable按钮一刷新就没了,纯粹视觉提示作用,所以在后端models里为user加了一个resend_right,当为True ...

  2. Python并发编程系列之多线程

    1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...

  3. [Python爬虫] 5-爬虫进阶(多线程爬虫/动态网页抓取/图形验证码识别)

    # I.多线程爬虫 # 1)概念:多线程是为了同步完成多项任务,通过提高资源使用效率来提高系统的效率 # 线程:火车的车厢,进程:火车头 # # 2)threading模块:专门提供用来做多线程编程的 ...

  4. python多线程好还是多协程好_深入浅析python中的多进程、多线程、协程

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...

  5. python实用程序育儿法_Python多线程 简明例子

    Python多线程 简明例子 (2010-03-11 15:15:09) Python多线程 简明例子 综述 多线程是程序设计中的一个重要方面,尤其是在服务器Deamon程序方面.无论何种系统,线程调 ...

  6. [PYTHON] 核心编程笔记(18.多线程编程)

    18.1 引言/动机 18.2 线程和进程 18.2.1 什么是进程(重量级进程)? 计算机程序只不过是磁盘中可执行的,二进制(或其他类型)的数据,他们只有在被读取到内存中,被操作系统调用时才开始他们 ...

  7. python基础代码库-python基础:一个非常简单且详细的多线程代码

    前言 多线程的好处应该不用多说吧?python语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了 Python 的多线程编程. 在实际应用,多线程还是很有用的,比如有时候可以 ...

  8. Python 并发编程之使用多线程和多处理器

    在Python编码中我们经常讨论的一个方面就是如何优化模拟执行的性能.尽管在考虑量化代码时NumPy.SciPy和pandas在这方面已然非常有用,但在构建事件驱动系统时我们无法有效地使用这些工具.有 ...

  9. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

最新文章

  1. 《JAVA练习题目5》 请在类中定义计算阶乘的方法完成本题目的求解
  2. Hystrix 熔断器02 —— hystrix 案例之高并发测试
  3. Eclipse tomcat Web页面调试
  4. 常用的分布式事务解决方案介绍
  5. goldilocks数据库_如何找到您的开源Goldilocks区域
  6. python sqlite
  7. san分布式共享文件系统_基于SAN存储共享卷实现openstack高可用的方法与流程
  8. Google人工智能面试·真·题(附参考答案+攻略)
  9. LeetCode Closest Binary Search Tree Value II
  10. mysql修改information_schema表时的错误
  11. 转载:16种鲜鱼的做法
  12. Zinc 全文搜索引擎Elasticsearch轻量级替代品
  13. 已解决mybatis报错:Invalid bound statement (not found)
  14. RedisBloom 插件布隆过滤器,布谷鸟过滤器,Count-Min Sketch,TOPK使用详解
  15. android禁止手机访问某个ip,如何禁止手机访问某个网站
  16. Windows 无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目
  17. Loadrunner 11安装教程
  18. 标题: 连接到服务器 ------------------------------ 无法连接到
  19. 海思麒麟linux内核,麒麟海思Linux(Ubuntu)安装编译安装Nginx
  20. 涂鸦WIFI模组方案(MCU SDK)

热门文章

  1. Apache CXF框架简介
  2. 关于爬取arXiv论坛论文并按照论文主题进行分类的办法
  3. Unity加载优化-将基于LZMA的ab压缩方案修改为LZ4压缩的过程
  4. MySQL性能指标TPS+QPS+IOPS压测
  5. 好莱坞的十大故事引擎
  6. Linux基础命令----tailf 跟踪文件输出
  7. 网络综合布线测试的新选择-AEM
  8. 【期末复习】计算机组成原理
  9. 真相:为什么投简历总是没回音?
  10. 网站如何快速被收录,只需做到以下几点?