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的批量远程管理和部署工具Fabric用法实例
Jan 23 Python
Python中查看文件名和文件路径
Mar 31 Python
Python队列的定义与使用方法示例
Jun 24 Python
Python学习笔记之视频人脸检测识别实例教程
Mar 06 Python
记录Python脚本的运行日志的方法
Jun 05 Python
python 计算平均平方误差(MSE)的实例
Jun 29 Python
python实现简单日志记录库glog的使用
Dec 13 Python
使用Tensorflow将自己的数据分割成batch训练实例
Jan 20 Python
浅谈Python中的继承
Jun 19 Python
python正则表达式的懒惰匹配和贪婪匹配说明
Jul 13 Python
python小技巧——将变量保存在本地及读取
Nov 13 Python
python必学知识之文件操作(建议收藏)
May 30 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生成随机数或者字符串的代码
2008/09/05 PHP
PHP 简单数组排序实现代码
2009/08/05 PHP
PHP 日期加减的类,很不错
2009/10/10 PHP
php json与xml序列化/反序列化
2013/10/28 PHP
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
js CSS操作方法集合
2008/10/31 Javascript
ASP SQL防注入的方法
2008/12/25 Javascript
Extjs Gird 支持中文拼音排序实现代码
2013/04/15 Javascript
JQuery事件e参数的方法preventDefault()取消默认行为
2013/09/26 Javascript
div模拟选择框示例代码
2013/11/03 Javascript
js无刷新操作table的行和列
2014/03/27 Javascript
JavaScript设计模式之单例模式实例
2014/09/24 Javascript
node.js中的buffer.fill方法使用说明
2014/12/14 Javascript
javascript实现动态加载CSS
2015/01/26 Javascript
JQuery的ON()方法支持的所有事件罗列
2015/02/28 Javascript
javascript禁止访客复制网页内容的实现代码
2015/08/05 Javascript
jquery实现超简洁的TAB选项卡效果代码
2015/08/28 Javascript
把普通对象转换成json格式的对象的简单实例
2016/07/04 Javascript
jQuery制作网页版选项卡
2016/07/28 Javascript
angularJs中跳转到指定的锚点实例($anchorScroll)
2018/08/31 Javascript
vue鼠标悬停事件实例详解
2019/04/01 Javascript
基于vue 动态菜单 刷新空白问题的解决
2020/08/06 Javascript
利用js canvas实现五子棋游戏
2020/10/11 Javascript
element 动态合并表格的步骤
2020/12/31 Javascript
对python中raw_input()和input()的用法详解
2018/04/22 Python
Python3多进程 multiprocessing 模块实例详解
2018/06/11 Python
Selenium鼠标与键盘事件常用操作方法示例
2018/08/13 Python
python实现自动解数独小程序
2019/01/21 Python
Python画图高斯分布的示例
2019/07/10 Python
python实现静态服务器
2019/09/05 Python
幼儿教师演讲稿
2014/05/06 职场文书
党员查摆剖析材料
2014/10/10 职场文书
努力学习保证书
2015/02/26 职场文书
2015年上半年计生工作总结
2015/03/30 职场文书
高三毕业感言
2015/07/30 职场文书