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中使用logging模块代替print(logging简明指南)
Jul 09 Python
Python输出PowerPoint(ppt)文件中全部文字信息的方法
Apr 28 Python
django model去掉unique_together报错的解决方案
Oct 18 Python
PyCharm代码格式调整方法
May 23 Python
python实现判断一个字符串是否是合法IP地址的示例
Jun 04 Python
使用Python制作自动推送微信消息提醒的备忘录功能
Sep 06 Python
python提取包含关键字的整行数据方法
Dec 11 Python
Python pandas自定义函数的使用方法示例
Nov 20 Python
python几种常用功能实现代码实例
Dec 25 Python
基于keras输出中间层结果的2种实现方式
Jan 24 Python
在Ubuntu中安装并配置Pycharm教程的实现方法
Jan 06 Python
python使用openpyxl库读写Excel表格的方法(增删改查操作)
May 02 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
PHP实现按之字形顺序打印二叉树的方法
2018/01/16 PHP
js选取多个或单个元素的实现代码(用class)
2012/08/22 Javascript
jquery获取特定name所有选中的checkbox,支持IE9标准模式
2013/03/18 Javascript
同域jQuery(跨)iframe操作DOM(实例讲解)
2013/12/19 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
2015/05/16 Javascript
vue component组件使用方法详解
2017/07/14 Javascript
vue百度地图 + 定位的详解
2019/05/13 Javascript
vue-element-admin 菜单标签失效的解决方式
2019/11/12 Javascript
javascript实现留言板功能
2020/02/08 Javascript
[28:28]Ti4 冒泡赛第二天NEWBEE vs NaVi 2
2014/07/15 DOTA
[56:56]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
浅谈numpy中linspace的用法 (等差数列创建函数)
2017/06/07 Python
创建pycharm的自定义python模板方法
2018/05/23 Python
在Python中增加和插入元素的示例
2018/11/01 Python
Django自定义模板过滤器和标签的实现方法
2019/08/21 Python
python使用socket实现的传输demo示例【基于TCP协议】
2019/09/24 Python
python绘制规则网络图形实例
2019/12/09 Python
解决python多线程报错:AttributeError: Can't pickle local object问题
2020/04/08 Python
Python接口测试数据库封装实现原理
2020/05/09 Python
Python logging日志模块 配置文件方式
2020/07/12 Python
中外合拍动画首获奥斯卡提名,“上海出品”《飞奔去月球》能否拿下最终大奖?
2021/03/16 国漫
字中字效果的实现【html5实例】
2016/05/03 HTML / CSS
微信小程序canvas实现水平、垂直居中效果
2020/02/05 HTML / CSS
意大利奢华内衣制造商:Cosabella
2017/08/29 全球购物
北京SQL新华信咨询
2016/09/30 面试题
大学生涯自我鉴定
2014/01/16 职场文书
求职信的最佳写作思路
2014/02/01 职场文书
档案室主任岗位职责
2014/02/12 职场文书
人资专员岗位职责
2014/04/04 职场文书
安全生产目标责任书
2014/04/14 职场文书
捐助倡议书范文
2014/04/15 职场文书
质量保证书范本
2014/04/29 职场文书
六一儿童节标语
2014/10/08 职场文书
泰坦尼克号观后感
2015/06/04 职场文书
行政复议决定书
2015/06/24 职场文书
2016暑期师德培训心得体会
2016/01/09 职场文书