浅谈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 相关文章推荐
Tensorflow简单验证码识别应用
May 25 Python
python 矩阵增加一行或一列的实例
Apr 04 Python
Python错误处理操作示例
Jul 18 Python
使用python实现快速搭建简易的FTP服务器
Sep 12 Python
Pycharm2017版本设置启动时默认自动打开项目的方法
Oct 29 Python
对pandas中iloc,loc取数据差别及按条件取值的方法详解
Nov 06 Python
将Python字符串生成PDF的实例代码详解
May 17 Python
Python sys模块常用方法解析
Feb 20 Python
python 实现两个线程交替执行
May 02 Python
python中pop()函数的语法与实例
Dec 01 Python
Python3.9.0 a1安装pygame出错解决全过程(小结)
Feb 02 Python
python Django框架快速入门教程(后台管理)
Jul 21 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
基于数据库的在线人数,日访问量等统计
2006/10/09 PHP
php链表用法实例分析
2015/07/09 PHP
php文件包含目录配置open_basedir的使用与性能详解
2017/04/03 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
2017/09/17 PHP
PHP7 参数处理机制修改
2021/03/09 PHP
Nigma vs AM BO3 第一场2.13
2021/03/10 DOTA
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
File文件控件,选中文件(图片,flash,视频)即立即预览显示
2009/04/09 Javascript
网页右侧悬浮滚动在线qq客服代码示例
2014/04/28 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
移动手机APP手指滑动切换图片特效附源码下载
2015/11/30 Javascript
jQuery操作Table技巧大汇总
2016/01/23 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
微信小程序使用radio显示单选项功能【附源码下载】
2017/12/11 Javascript
JS可断点续传文件上传实现代码解析
2020/07/30 Javascript
Python获取Linux系统下的本机IP地址代码分享
2014/11/07 Python
Python数据结构与算法之二叉树结构定义与遍历方法详解
2017/12/12 Python
使用Eclipse如何开发python脚本
2018/04/11 Python
python处理csv中的空值方法
2018/06/22 Python
django drf框架中的user验证以及JWT拓展的介绍
2019/08/12 Python
Flask框架 CSRF 保护实现方法详解
2019/10/30 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
2020/03/30 Python
python实现126邮箱发送邮件
2020/05/20 Python
Python扫描端口的实现
2021/01/25 Python
突破canvas语法限制 让他支持链式语法
2012/12/24 HTML / CSS
基于Modernizr 让网站进行优雅降级的分析
2013/04/21 HTML / CSS
HTML5新增加的功能详解
2016/09/05 HTML / CSS
努比亚手机官网:nubia
2016/10/06 全球购物
中邮全球便购:中国邮政速递物流
2017/03/04 全球购物
校园门卫岗位职责
2013/12/09 职场文书
告诉你怎样写创业计划书
2014/01/27 职场文书
校长竞聘演讲稿
2014/05/16 职场文书
2015年初三班主任工作总结
2015/05/21 职场文书
六一晚会主持词开场白
2015/05/28 职场文书
如何用python识别滑块验证码中的缺口
2021/04/01 Python
一些让Python代码简洁的实用技巧总结
2021/08/23 Python