浅谈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实现对一个完整url进行分割的方法
Apr 29 Python
Python中处理字符串之isalpha()方法的使用
May 18 Python
Python测试人员需要掌握的知识
Feb 08 Python
Windows 7下Python Web环境搭建图文教程
Mar 20 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
Dec 04 Python
Python GUI库PyQt5图形和特效样式QSS介绍
Feb 25 Python
pycharm工具连接mysql数据库失败问题
Apr 01 Python
如何基于python对接钉钉并获取access_token
Apr 21 Python
Python实现转换图片背景颜色代码
Apr 30 Python
django自带的权限管理Permission用法说明
May 13 Python
30行Python代码实现高分辨率图像导航的方法
May 22 Python
在keras下实现多个模型的融合方式
May 23 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
window+nginx+php环境配置 附配置搭配说明
2010/12/29 PHP
layui框架实现文件上传及TP3.2.3(thinkPHP)对上传文件进行后台处理操作示例
2018/05/12 PHP
php实现的简单多进程服务器类完整示例
2020/02/01 PHP
JavaScript 异步调用框架 (Part 3 - 代码实现)
2009/08/04 Javascript
利用JS重写Cognos右键菜单的实现代码
2010/04/11 Javascript
JQuery 文本框回车跳到下一个文本框示例代码
2013/08/30 Javascript
javascript抽象工厂模式详细说明
2014/12/16 Javascript
jquery实现简单实用的打分程序实例
2015/07/23 Javascript
JavaScript的jQuery库中function的存在和参数问题
2015/08/13 Javascript
JavaScript实现元素滚动条到达一定位置循环追加内容
2017/12/28 Javascript
angularjs实现table增加tr的方法
2018/02/27 Javascript
Vue项目History模式404问题解决方法
2018/10/31 Javascript
angular中如何绑定iframe中src的方法
2019/02/01 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
ng-alain的sf如何自定义部件的流程
2020/06/12 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
vue使用exif获取图片旋转,压缩的示例代码
2020/12/11 Vue.js
原生js实现自定义滚动条组件
2021/01/20 Javascript
Python 代码性能优化技巧分享
2012/08/07 Python
Python实现自动登录百度空间的方法
2017/06/10 Python
Django视图和URL配置详解
2018/01/31 Python
matplotlib.pyplot画图 图片的二进制流的获取方法
2018/05/24 Python
pandas读取CSV文件时查看修改各列的数据类型格式
2019/07/07 Python
pytorch实现用Resnet提取特征并保存为txt文件的方法
2019/08/20 Python
Python如何计算语句执行时间
2019/11/22 Python
使用python动态生成波形曲线的实现
2019/12/04 Python
adidas官方旗舰店:德国运动用品制造商
2017/11/25 全球购物
FC-Moto美国:欧洲最大的摩托车服装和头盔商店之一
2019/08/24 全球购物
澳大利亚二手奢侈品网站:Modsie
2019/09/23 全球购物
电脑教师的自我评价
2013/12/18 职场文书
趣味比赛活动方案
2014/02/15 职场文书
如何写自我评价?自我评价写什么好?
2014/03/14 职场文书
合作意向书范本
2014/03/31 职场文书
离婚协议书范文2014(夫妻感情破裂)
2014/12/14 职场文书
校友会致辞
2015/07/30 职场文书
配置nginx负载均衡
2022/05/06 Servers