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 相关文章推荐
Django中更新多个对象数据与删除对象的方法
Jul 17 Python
python 批量修改/替换数据的实例
Jul 25 Python
python Pexpect 实现输密码 scp 拷贝的方法
Jan 03 Python
使用python接入微信聊天机器人
Mar 31 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
Aug 05 Python
python RC4加密操作示例【测试可用】
Sep 26 Python
Python脚本去除文件的只读性操作
Mar 05 Python
python3 使用openpyxl将mysql数据写入xlsx的操作
May 15 Python
Python中内建模块collections如何使用
May 27 Python
keras读取训练好的模型参数并把参数赋值给其它模型详解
Jun 15 Python
Pytest测试框架基本使用方法详解
Nov 25 Python
Python基于mediainfo批量重命名图片文件
Dec 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 星际争霸
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
HTML TO JavaScript 转换
2006/06/26 Javascript
js键盘上下左右键怎么触发function(实例讲解)
2013/12/14 Javascript
javascript中数组的concat()方法使用介绍
2013/12/18 Javascript
parentElement,srcElement的使用小结
2014/01/13 Javascript
使用JavaScript链式编程实现模拟Jquery函数
2014/12/21 Javascript
js对象继承之原型链继承实例
2015/01/10 Javascript
浅析JavaScript中的事件机制
2015/06/04 Javascript
AngularJS 最常用的功能汇总
2016/02/17 Javascript
Svg.js实例教程及使用手册详解(一)
2016/05/16 Javascript
Bootstrap按钮功能之查询按钮和重置按钮
2016/10/26 Javascript
Vue计算属性的学习笔记
2017/03/22 Javascript
Bootstrap fileinput文件上传组件使用详解
2017/06/06 Javascript
Angular resolve基础用法详解
2018/10/03 Javascript
[52:10]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第二场 6.3
2018/06/04 DOTA
[01:51]开启你的城市传奇 完美世界城市挑战赛开始报名
2018/10/09 DOTA
[05:31]干嘛呢兄弟!DOTA2 TI9语音轮盘部分出处
2019/05/14 DOTA
[01:02:00]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第三场 1月24日
2021/03/11 DOTA
基于Python实现的百度贴吧网络爬虫实例
2015/04/17 Python
如何高效使用Python字典的方法详解
2017/08/31 Python
Python如何生成树形图案
2018/01/03 Python
Python退火算法在高次方程的应用
2018/07/26 Python
利用python循环创建多个文件的方法
2018/10/25 Python
基于python的socket实现单机五子棋到双人对战
2020/03/24 Python
如何基于python测量代码运行时间
2019/12/25 Python
Python如何实现线程间通信
2020/07/30 Python
澳大利亚领先的睡衣品牌:Peter Alexander
2016/08/16 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
铣工实训报告
2014/11/05 职场文书
论文评审意见
2015/06/05 职场文书
运动会加油稿30字
2015/07/21 职场文书
基于Redis延迟队列的实现代码
2021/05/13 Redis
新手必备之MySQL msi版本下载安装图文详细教程
2021/05/21 MySQL
python使用PySimpleGUI设置进度条及控件使用
2021/06/10 Python
Java方法重载和方法重写的区别到底在哪?
2021/06/11 Java/Android