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脚本使得web页面上的代码高亮显示
Apr 24 Python
Python实现TCP协议下的端口映射功能的脚本程序示例
Jun 14 Python
Python中static相关知识小结
Jan 02 Python
TensorFlow中权重的随机初始化的方法
Feb 11 Python
python定向爬虫校园论坛帖子信息
Jul 23 Python
python多个模块py文件的数据共享实例
Jan 11 Python
python3.6环境安装+pip环境配置教程图文详解
Jun 20 Python
详解python和matlab的优势与区别
Jun 28 Python
python3.7环境下安装Anaconda的教程图解
Sep 10 Python
简单了解python元组tuple相关原理
Dec 02 Python
最小二乘法及其python实现详解
Feb 24 Python
python生成13位或16位时间戳以及反向解析时间戳的实例
Mar 03 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中var_export与var_dump的区别分析
2010/08/21 PHP
Views rows style模板重写代码
2011/05/16 PHP
php实现单链表的实例代码
2013/03/22 PHP
PHP中常用的数组操作方法笔记整理
2016/05/16 PHP
深入浅析Yii admin的权限控制
2016/08/31 PHP
YII分模块加载路由的实现方法
2018/10/01 PHP
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
jQuery asp.net 用json格式返回自定义对象
2010/04/07 Javascript
Jquery插件写法笔记整理
2012/09/06 Javascript
用jquery生成二级菜单的实例代码
2013/06/24 Javascript
jquery固定底网站底部菜单效果
2013/08/13 Javascript
js创建对象几种方式的优缺点对比
2016/09/28 Javascript
BootStrap整体框架之基础布局组件
2016/12/15 Javascript
纯js实现悬浮按钮组件
2016/12/17 Javascript
js中创建对象的几种方式
2017/02/05 Javascript
详解如何构建Angular项目目录结构
2017/07/13 Javascript
ES6关于Promise的用法详解
2018/05/07 Javascript
nodejs更改项目端口号的方法
2018/05/13 NodeJs
微信小程序实现左右联动的实战记录
2018/07/05 Javascript
python使用wxPython打开并播放wav文件的方法
2015/04/24 Python
Python实现的递归神经网络简单示例
2017/08/11 Python
pandas条件组合筛选和按范围筛选的示例代码
2019/08/26 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
2020/05/21 Python
HTML5的hidden属性兼容老浏览器的方法
2014/04/23 HTML / CSS
HTML5+WebSocket实现多文件同时上传的实例
2016/12/29 HTML / CSS
AMAVII眼镜官网:时尚和设计师太阳镜
2019/05/05 全球购物
秋游活动策划方案
2014/02/16 职场文书
爱的奉献演讲稿
2014/09/10 职场文书
北京离婚协议书范文2014
2014/09/29 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
2014年纪检监察工作总结
2014/11/11 职场文书
python实现socket简单通信的示例代码
2021/04/13 Python
JavaScript展开运算符和剩余运算符的区别详解
2022/02/18 Javascript
Minikube搭建Kubernetes集群
2022/03/31 Servers
Android Gradle 插件自定义Plugin实现注意事项
2022/06/16 Java/Android
Go中使用gjson来操作JSON数据的实现
2022/08/14 Golang