浅谈Python线程的同步互斥与死锁


Posted in Python onMarch 22, 2020

线程间通信方法

    1. 通信方法

线程间使用全局变量进行通信

    2. 共享资源争夺

共享资源:多个进程或者线程都可以操作的资源称为共享资源。对共享资源的操作代码段称为临界区。

影响 : 对共享资源的无序操作可能会带来数据的混乱,或者操作错误。此时往往需要同步互斥机制协调操作顺序。

    3. 同步互斥机制

同步 : 同步是一种协作关系,为完成操作,多进程或者线程间形成一种协调,按照必要的步骤有序执行操作。两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。比如 A 任务的运行依赖于 B 任务产生的数据。

浅谈Python线程的同步互斥与死锁

互斥 : 互斥是一种制约关系,当一个进程或者线程占有资源时会进行加锁处理,此时其他进程线程就无法操作该资源,直到解锁后才能操作。一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源

浅谈Python线程的同步互斥与死锁

线程同步互斥方法

    线程Event同步

from threading import Event
e = Event() 创建线程event对象
e.wait([timeout]) 阻塞等待e被set
e.set() 设置e,使wait结束阻塞
e.clear() 使e回到未被设置状态
e.is_set() 查看当前e是否被设置

示例:

import time
import threading
 
event = threading.Event()
 
 
# 红绿灯
def lighter():
  count = 0
  event.set() # 刚进来的时候是绿灯
  while True:
    if 4 < count < 10:
      event.clear() # 清除设置,阻塞等待
      print("[信号灯]:红,不能通行", count)
    elif count >= 10: # 添加设置,继续执行
      event.set()
      count = 0
    else:
      event.set() # 添加设置,继续执行
      print("[信号灯]:绿灯,可以通行", count)
    time.sleep(1)
    count += 1
 
 
# 汽车
def car(name):
  while True:
    if event.is_set():
      print("{0}: 绿灯 , 走起...".format(name))
      time.sleep(1)
    else:
      print("{0}: 红灯 , 停车...".format(name))
      event.wait()
      print("{0}: 绿灯亮了 , 继续前进...".format(name))
 
 
light = threading.Thread(target=lighter, )
light.start()
car1 = threading.Thread(target=car, args=("小跑",))
car1.start()

    线程锁 Lock

from threading import Lock
lock = Lock() #创建锁对象
lock.acquire() #上锁 如果lock已经上锁再调用会阻塞
lock.release() #解锁

with lock: 上锁

with代码块结束自动解锁

示例:

from threading import Thread, Lock
from time import sleep
 
a = b = 0
lock = Lock()
 
 
# 子线程输出a b
def value():
  while True:
    lock.acquire() # 上锁
    if a != b:
      print("a = %d,b = %d" % (a, b))
    lock.release() # 解锁
 
 
t = Thread(target=value)
t.start()
 
# 主线程加锁更改a b时候,子线程处理a b 时也要进行加锁,重复加锁就会阻塞等待主线程处理结束
# 同理主进程再次更改a b 时等 子进程结束才可以
while True:
  with lock: # 自动上/解锁
    a += 1
    b += 1
t.join

死锁及其处理

    1. 定义

        死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

    2. 死锁产生条件

        【互斥条件】:指线程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

       【请求和保持条件】:指线程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求线程阻塞,但又对自己已获得的其它资源保持不放。

        【不剥夺条件】:指线程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放,通常CPU内存资源是可以被系统强行调配剥夺的。

        【环路等待条件】:指在发生死锁时,必然存在一个线程——资源的环形链,即进程集合{T0,T1,T2,···,Tn}中的T0正在等待一个T1占用的资源;T1正在等待T2占用的资源,……,Tn正在等待已被T0占用的资源。

         简单来说造成死锁的原因可以概括成三句话:

【1】当前线程拥有其他线程需要的资源

【2】当前线程等待其他线程已拥有的资源

【3】都不放弃自己拥有的资源

浅谈Python线程的同步互斥与死锁

 T1拥有R1,T2拥有R2。T1请求使用R2,T2请求使用R1,但是T1,T2 都不愿释放R1,R2,互相一直等待下去,造成死锁

    3. 如何避免死锁

        死锁是我们非常不愿意看到的一种现象,我们要尽可能避免死锁的情况发生。通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率。

from threading import Lock, Thread
 
 
# 交易类
class Account:
  def __init__(self, _id, balance, lock):
    self.id = _id
    self.balance = balance
    self.lock = lock # 各自账户锁
 
  # 取钱
  def withdraw(self, amount):
    self.balance -= amount
 
  # 存钱
  def deposit(self, amount):
    self.balance += amount
 
  # 查看账户
  def get_balance(self):
    return self.balance
 
 
# 转账
def transfer(from_, to, amount):
  if from_.lock.acquire(): # 锁住自己的账户
    from_.withdraw(amount) # 自己账户减少
    if to.lock.acquire(): # 锁住对方账户
      to.deposit(amount) # 对方账户增加
      to.lock.release() # 解锁对方账户
    from_.lock.release() # 自己账户解锁
  print("转账完成")
 
 
Abby = Account("Abby", 5000, Lock())
Balen = Account("Balen", 3000, Lock())
 
t = Thread(target=transfer, args=(Abby, Balen, 1000))
t2 = Thread(target=transfer, args=(Balen, Abby, 500))
t.start()
t2.start()
t.join()
t2.join()
 
print("Abby:", Abby.get_balance())
print("Balen:", Balen.get_balance())

到此这篇关于浅谈Python线程的同步互斥与死锁的文章就介绍到这了,更多相关Python线程同步互斥与死锁内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现字典按照value进行排序的方法分析
Dec 23 Python
PyQt4实现下拉菜单可供选择并打印出来
Apr 20 Python
Python爬虫实现全国失信被执行人名单查询功能示例
May 03 Python
PHP实现发送和接收JSON请求
Jun 07 Python
Python基于OpenCV库Adaboost实现人脸识别功能详解
Aug 25 Python
Python字典创建 遍历 添加等实用基础操作技巧
Sep 13 Python
详解Python读取yaml文件多层菜单
Mar 23 Python
解决python中导入win32com.client出错的问题
Jul 26 Python
python定义类的简单用法
Jul 24 Python
python正则表达式 匹配反斜杠的操作方法
Aug 07 Python
Django haystack实现全文搜索代码示例
Nov 28 Python
Django debug为True时,css加载失败的解决方案
Apr 24 Python
Django 项目布局方法(值得推荐)
Mar 22 #Python
python实现吃苹果小游戏
Mar 21 #Python
python实现贪吃蛇游戏源码
Mar 21 #Python
python实现微信打飞机游戏
Mar 24 #Python
Python类的动态绑定实现原理
Mar 21 #Python
Python类和实例的属性机制原理详解
Mar 21 #Python
Python生成器常见问题及解决方案
Mar 21 #Python
You might like
PHP入门
2006/10/09 PHP
收集的PHP中与数组相关的函数
2007/03/22 PHP
PHP MVC框架skymvc支持多文件上传
2016/05/26 PHP
php命名空间设计思想、用法与缺点分析
2019/07/17 PHP
自己的js工具 Event封装
2009/08/21 Javascript
你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用
2013/04/23 Javascript
JQuery 在线引用及测试引用是否成功
2014/06/24 Javascript
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
2014/07/23 Javascript
node.js中的fs.rename方法使用说明
2014/12/16 Javascript
JavaScript设置表单上传时文件个数的方法
2015/08/11 Javascript
javascript关于继承解析
2016/05/10 Javascript
js动态添加的DIV中的onclick事件简单实例
2016/07/25 Javascript
js实现多图左右切换功能
2016/08/04 Javascript
JavaScript排序算法动画演示效果的实现方法
2016/10/18 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
解决vue.js在编写过程中出现空格不规范报错的问题
2017/09/20 Javascript
JS写XSS cookie stealer来窃取密码的步骤详解
2017/11/20 Javascript
深入学习js函数的隐式参数 arguments 和 this
2019/06/24 Javascript
基于javascript实现日历功能原理及代码实例
2020/05/07 Javascript
Python修改MP3文件的方法
2015/06/15 Python
python中类和实例如何绑定属性与方法示例详解
2017/08/18 Python
Python判断一个三位数是否为水仙花数的示例
2018/11/13 Python
基于numpy中数组元素的切片复制方法
2018/11/15 Python
itchat-python搭建微信机器人(附示例)
2019/06/11 Python
python3+PyQt5 数据库编程--增删改实例
2019/06/17 Python
Python终端输出彩色字符方法详解
2020/02/11 Python
python利用 keyboard 库记录键盘事件
2020/10/16 Python
手把手教你实现一个canvas智绘画板的方法
2019/03/04 HTML / CSS
奇怪的鱼:Weird Fish
2018/03/18 全球购物
Yves Rocher捷克官方网站:植物化妆品的创造者
2019/07/31 全球购物
荷兰音乐会和音乐剧门票订购网站:Topticketshop
2019/08/27 全球购物
CSS代码检查工具stylelint的使用方法详解
2021/03/27 HTML / CSS
幼儿园中班新学期寄语
2014/01/18 职场文书
人事专员的职责
2014/02/26 职场文书
搞笑结婚保证书
2015/05/08 职场文书
2019财务管理制度最新范本!
2019/07/09 职场文书