python线程中同步锁详解


Posted in Python onApril 27, 2018

在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock Rlock Semaphore Event Condition 用来保证线程之间的同步,后者保证访问共享变量的互斥问题

Lock & RLock:互斥锁 用来保证多线程访问共享变量的问题
Semaphore对象:Lock互斥锁的加强版,可以被多个线程同时拥有,而Lock只能被某一个线程同时拥有。
Event对象: 它是线程间通信的方式,相当于信号,一个线程可以给另外一个线程发送信号后让其执行操作。
Condition对象:其可以在某些事件触发或者达到特定的条件后才处理数据

1、Lock(互斥锁)

请求锁定 — 进入锁定池等待 — 获取锁 — 已锁定 — 释放锁

Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。

可以认为Lock有一个锁定池,当线程请求锁定时,将线程至于池中,直到获得锁定后出池。池中的线程处于状态图中的同步阻塞状态。

构造方法:
Lock()

实例方法:
acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。
release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。

if mutex.acquire():
 counter += 1
 print "I am %s, set counter:%s" % (self.name, counter)
  mutex.release()

2、RLock(可重入锁)

RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了“拥有的线程”和“递归等级”的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。

可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用 acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。

构造方法:
RLock()

实例方法:
acquire([timeout])/release(): 跟Lock差不多。

3、Semaphore(共享对象访问)

咱们再聊聊Semaphore ,说实话Semaphore是我最晚使用的同步锁,以前类似的实现,是我用Rlock实现的,相对来说有些绕,毕竟Rlock 是需要成对的锁定和开锁的》。。。

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

直接上代码,我们把semaphore控制为3,也就是说,同时有3个线程可以用这个锁,剩下的线程也之只能是阻塞等待了…

#coding:utf-8
#blog xiaorui.cc
import time
import threading

semaphore = threading.Semaphore(3)

def func():
 if semaphore.acquire():
  for i in range(3):
   time.sleep(1)
   print (threading.currentThread().getName() + '获取锁')
  semaphore.release()
  print (threading.currentThread().getName() + ' 释放锁')


for i in range(5):
 t1 = threading.Thread(target=func)
 t1.start()

4、Event(线程间通信)

Event内部包含了一个标志位,初始的时候为false。
可以使用使用set()来将其设置为true;
或者使用clear()将其从新设置为false;
可以使用is_set()来检查标志位的状态;

另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。

import threading
import time

class MyThread(threading.Thread):
 def __init__(self, signal):
  threading.Thread.__init__(self)
  self.singal = signal

 def run(self):
  print "I am %s,I will sleep ..."%self.name
  self.singal.wait()
  print "I am %s, I awake..." %self.name

if __name__ == "__main__":
 singal = threading.Event()
 for t in range(0, 3):
  thread = MyThread(singal)
  thread.start()

 print "main thread sleep 3 seconds... "
 time.sleep(3)

 singal.set()

5、Condition(线程同步)

可以把Condition理解为一把高级的琐,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。threadiong.Condition在内部维护一个琐对象(默认是RLock),可以在创建Condigtion对象的时候把琐对象作为参数传入。Condition也提供了acquire, release方法,其含义与琐的acquire, release方法一致,其实它只是简单的调用内部琐对象的对应的方法而已。Condition还提供了如下方法(特别要注意:这些方法只有在占用琐(acquire)之后才能调用,否则将会报RuntimeError异常。):

Condition.wait([timeout]):

wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。

Condition.notify():

唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的琐。

Condition.notify_all()
Condition.notifyAll()

唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

对于Condition有个例子,大家可以观摩下。

from threading import Thread, Condition
import time
import random

queue = []
MAX_NUM = 10
condition = Condition()

class ProducerThread(Thread):
 def run(self):
  nums = range(5)
  global queue
  while True:
   condition.acquire()
   if len(queue) == MAX_NUM:
    print "Queue full, producer is waiting"
    condition.wait()
    print "Space in queue, Consumer notified the producer"
   num = random.choice(nums)
   queue.append(num)
   print "Produced", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


class ConsumerThread(Thread):
 def run(self):
  global queue
  while True:
   condition.acquire()
   if not queue:
    print "Nothing in queue, consumer is waiting"
    condition.wait()
    print "Producer added something to queue and notified the consumer"
   num = queue.pop(0)
   print "Consumed", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


ProducerThread().start()
ConsumerThread().start()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用Python写一段用户登录的程序代码
Apr 22 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
Apr 28 Python
Python实现 版本号对比功能的实例代码
Apr 18 Python
python监控进程状态,记录重启时间及进程号的实例
Jul 15 Python
python实现美团订单推送到测试环境,提供便利操作示例
Aug 09 Python
用Python实现校园通知更新提醒功能
Nov 23 Python
使用Python实现 学生学籍管理系统
Nov 26 Python
keras 特征图可视化实例(中间层)
Jan 24 Python
python实现双人五子棋(终端版)
Dec 30 Python
Python制作运行进度条的实现效果(代码运行不无聊)
Feb 24 Python
pytorch 实现L2和L1正则化regularization的操作
Mar 03 Python
python 遍历磁盘目录的三种方法
Apr 02 Python
python数字图像处理之高级形态学处理
Apr 27 #Python
python线程池threadpool实现篇
Apr 27 #Python
python数字图像处理之骨架提取与分水岭算法
Apr 27 #Python
python多线程之事件Event的使用详解
Apr 27 #Python
python线程池threadpool使用篇
Apr 27 #Python
Python实现删除时保留特定文件夹和文件的示例
Apr 27 #Python
python中yaml配置文件模块的使用详解
Apr 27 #Python
You might like
最新的php 文件上传模型,支持多文件上传
2009/08/13 PHP
CI框架入门示例之数据库取数据完整实现方法
2014/11/05 PHP
php实现插入排序
2015/03/29 PHP
php的常量和变量实例详解
2017/06/27 PHP
在线编辑器的实现原理(兼容IE和FireFox)
2007/03/09 Javascript
Prototype源码浅析 Number部分
2012/01/16 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
js中通过split函数分割字符串成数组小例子
2013/09/21 Javascript
鼠标悬浮停留三秒后自动显示大图js代码
2014/09/09 Javascript
深入浅析Node.js 事件循环
2015/12/20 Javascript
基于JQuery实现图片轮播效果(焦点图)
2016/02/02 Javascript
纯JS代码实现一键分享功能
2016/04/20 Javascript
微信小程序自定义多选事件的实现代码
2018/05/17 Javascript
webpack中如何使用雪碧图的示例代码
2018/11/11 Javascript
jQuery Migrate 插件用法实例详解
2019/05/22 jQuery
微信小程序开发摇一摇功能
2019/11/22 Javascript
基于vue+echarts 数据可视化大屏展示的方法示例
2020/03/09 Javascript
[01:58]最残酷竞争 2016国际邀请赛中国区预选赛积分循环赛回顾
2016/06/28 DOTA
[50:59]2018DOTA2亚洲邀请赛 4.7 总决赛 LGD vs Mineski第四场
2018/04/10 DOTA
Python脚本处理空格的方法
2016/08/08 Python
在python环境下运用kafka对数据进行实时传输的方法
2018/12/27 Python
python 将字符串完成特定的向右移动方法
2019/06/11 Python
python将字母转化为数字实例方法
2019/10/04 Python
使用python快速在局域网内搭建http传输文件服务的方法
2019/11/14 Python
Python super()方法原理详解
2020/03/31 Python
Django项目uwsgi+Nginx保姆级部署教程实现
2020/04/19 Python
python温度转换华氏温度实现代码
2020/12/06 Python
Python实现我的世界小游戏源代码
2021/03/02 Python
阿根廷在线宠物商店:Puppis
2018/03/23 全球购物
美国伊甸园兄弟种子公司:Eden Brothers
2018/07/01 全球购物
美国在线乐器和设备商店:Musician’s Friend
2018/07/06 全球购物
保护母亲河倡议书
2014/04/14 职场文书
公益广告标语
2014/06/19 职场文书
群众路线剖析材料怎么写
2014/10/09 职场文书
情人节单身感言
2015/08/03 职场文书
用Python的绘图库(matplotlib)绘制小波能量谱
2021/04/17 Python