Python多线程同步Lock、RLock、Semaphore、Event实例


Posted in Python onNovember 21, 2014

一、多线程同步

由于CPython的python解释器在单线程模式下执行,所以导致python的多线程在很多的时候并不能很好地发挥多核cpu的资源。大部分情况都推荐使用多进程。

python的多线程的同步与其他语言基本相同,主要包含:

Lock & RLock :用来确保多线程多共享资源的访问。
Semaphore : 用来确保一定资源多线程访问时的上限,例如资源池。 
Event : 是最简单的线程间通信的方式,一个线程可以发送信号,其他的线程接收到信号后执行操作。 

二、实例

1)Lock & RLock

Lock对象的状态可以为locked和unlocked

使用acquire()设置为locked状态;
使用release()设置为unlocked状态。

如果当前的状态为unlocked,则acquire()会将状态改为locked然后立即返回。当状态为locked的时候,acquire()将被阻塞直到另一个线程中调用release()来将状态改为unlocked,然后acquire()才可以再次将状态置为locked。

Lock.acquire(blocking=True, timeout=-1),blocking参数表示是否阻塞当前线程等待,timeout表示阻塞时的等待时间 。如果成功地获得lock,则acquire()函数返回True,否则返回False,timeout超时时如果还没有获得lock仍然返回False。

实例:(确保只有一个线程可以访问共享资源)

import threading

import time

 

num = 0

lock = threading.Lock()

 

def func(st):

    global num

    print (threading.currentThread().getName() + ' try to acquire the lock')

    if lock.acquire():

        print (threading.currentThread().getName() + ' acquire the lock.' )

        print (threading.currentThread().getName() +" :%s" % str(num) )

        num += 1

        time.sleep(st)

        print (threading.currentThread().getName() + ' release the lock.'  )        

        lock.release()

 

t1 = threading.Thread(target=func, args=(8,))

t2 = threading.Thread(target=func, args=(4,))

t3 = threading.Thread(target=func, args=(2,))

t1.start()

t2.start()

t3.start()

结果:

Python多线程同步Lock、RLock、Semaphore、Event实例

RLock与Lock的区别是:RLock中除了状态locked和unlocked外还记录了当前lock的owner和递归层数,使得RLock可以被同一个线程多次acquire()。

2)Semaphore

Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

实例:(同时只有2个线程可以获得semaphore,即可以限制最大连接数为2):

import threading

import time
semaphore = threading.Semaphore(2)

 

def func():

    if semaphore.acquire():

        for i in range(5):

          print (threading.currentThread().getName() + ' get semaphore')

        semaphore.release()

        print (threading.currentThread().getName() + ' release semaphore')

        

        

for i in range(4):

  t1 = threading.Thread(target=func)

  t1.start()

结果:

Python多线程同步Lock、RLock、Semaphore、Event实例

3) Event

Event内部包含了一个标志位,初始的时候为false。
可以使用使用set()来将其设置为true;
或者使用clear()将其从新设置为false;
可以使用is_set()来检查标志位的状态;
另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。

实例: (线程间相互通信)

import logging

import threading

import time
logging.basicConfig(level=logging.DEBUG,

format="(%(threadName)-10s : %(message)s",

)
def wait_for_event_timeout(e, t):

    """Wait t seconds and then timeout"""

    while not e.isSet():

      logging.debug("wait_for_event_timeout starting")

      event_is_set = e.wait(t)

      logging.debug("event set: %s" % event_is_set)

    if event_is_set:

      logging.debug("processing event")

    else:

      logging.debug("doing other work")

      

e = threading.Event()

t2 = threading.Thread(name="nonblock",

target=wait_for_event_timeout,args=(e, 2))

t2.start()

logging.debug("Waiting before calling Event.set()")

time.sleep(7)

e.set()

logging.debug("Event is set")

运行结果:

Python多线程同步Lock、RLock、Semaphore、Event实例

三、其他

1) 线程局部变量

线程局部变量的值是跟线程相关的,区别与全局的变量。使用非常简单如下:

mydata = threading.local()

mydata.x = 1

2)对Lock,semaphore,condition等使用with关键字代替手动调用acquire()和release()。

Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之关系映射实例
Jun 10 Python
Python 探针的实现原理
Apr 23 Python
python编程通过蒙特卡洛法计算定积分详解
Dec 13 Python
Python cookbook(数据结构与算法)对切片命名清除索引的方法
Mar 13 Python
Python根据成绩分析系统浅析
Feb 11 Python
Python控制Firefox方法总结
Jun 03 Python
Anaconda之conda常用命令介绍(安装、更新、删除)
Oct 06 Python
Python 实现取多维数组第n维的前几位
Nov 26 Python
Python无头爬虫下载文件的实现
Apr 02 Python
pandas之分组groupby()的使用整理与总结
Jun 18 Python
Tensorflow使用Anaconda、pycharm安装记录
Jul 29 Python
Python爬取梨视频的示例
Jan 29 Python
python多进程操作实例
Nov 21 #Python
Python多进程通信Queue、Pipe、Value、Array实例
Nov 21 #Python
Python多进程同步Lock、Semaphore、Event实例
Nov 21 #Python
Python multiprocessing.Manager介绍和实例(进程间共享数据)
Nov 21 #Python
Python pickle类库介绍(对象序列化和反序列化)
Nov 21 #Python
Python和perl实现批量对目录下电子书文件重命名的代码分享
Nov 21 #Python
Python实现的下载8000首儿歌的代码分享
Nov 21 #Python
You might like
蝙蝠侠:侠影之谜
2020/03/04 欧美动漫
PHP 图像尺寸调整代码
2010/05/26 PHP
php实现的漂亮分页方法
2014/04/17 PHP
php数组添加与删除单元的常用函数实例分析
2015/02/16 PHP
php提交表单发送邮件的方法
2015/03/20 PHP
PHP安全上传图片的方法
2015/03/21 PHP
php实现的简单美国商品税计算函数
2015/07/13 PHP
php封装的smartyBC类完整实例
2016/10/19 PHP
DWZ+ThinkPHP开发时遇到的问题分析
2016/12/12 PHP
ajax 文件上传应用简单实现
2009/03/03 Javascript
jQuery新闻滚动插件 jquery.roller.js
2011/06/27 Javascript
7款风格新颖的jQuery/CSS3菜单导航分享
2013/04/23 Javascript
JavaScript里四舍五入函数round用法实例
2015/04/06 Javascript
详解AngularJS如何实现跨域请求
2016/08/22 Javascript
Bootstrap Multiselect 常用组件实现代码
2017/07/09 Javascript
highcharts 在angular中的使用示例代码
2017/09/20 Javascript
10 种最常见的 Javascript 错误(频率最高)
2018/02/08 Javascript
JavaScript实现的开关灯泡点击切换特效示例
2019/07/08 Javascript
vue如何搭建多页面多系统应用
2020/06/17 Javascript
详解Python中的文本处理
2015/04/11 Python
Python装饰器使用实例:验证参数合法性
2015/06/24 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
解决Python图形界面中设置尺寸的问题
2020/03/05 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
2020/08/07 Python
Python字符串及文本模式方法详解
2020/09/10 Python
基于canvas的骨骼动画的示例代码
2018/06/12 HTML / CSS
澳大利亚最受欢迎的美发和美容在线商店:Catwalk
2018/12/12 全球购物
英国PC组件和在线电脑商店:SCAN
2019/04/18 全球购物
大学生年度自我鉴定
2013/10/31 职场文书
大学专科求职信
2014/07/02 职场文书
个人简历自我评价怎么写
2015/03/10 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
AI:如何训练机器学习的模型
2021/04/16 Python
《王者天下》第4季首话新剧照 4月9日正式开播
2022/04/07 日漫
vue报错function () { [native code] },无法出现我们想要的内容 Unknown custom element
2022/04/11 Vue.js
Python中生成随机数据安全性、多功能性、用途和速度方面进行比较
2022/04/14 Python