Python的线程16 一分钟写个死锁,单身狗谈何爱情
Posted 雷学委
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python的线程16 一分钟写个死锁,单身狗谈何爱情相关的知识,希望对你有一定的参考价值。
正式的Python专栏第53篇,同学站住,别错过这个从0开始的文章!
前面学委介绍Python的线程15 可重入锁RLock,文末提到了死锁。
所以这篇补充一下死锁的概念
死锁 是什么?
想象一下,身边有哪些无法解开的问题?
是不是有个问题想要跟对象讲道理,一开始好好聊,还能说明白。然后聊着聊着,对象反将一军:“你不够爱我了!(爱会消失。。。)”
搞的一下子懵了,本来是要讨论谁不该干嘛干嘛的事情,就陷入了僵局。
对,死锁就是这种感觉。
这里不一样的是,讨论问题从两个人,变成了两个线程/进程(或者更多,多个就类似你爸妈在讨论该不该生叉烧比较好还是你比较好,最后追溯到爷爷奶奶,祖祖辈辈牵扯整个家族的问题)
好,简单概括这种感觉就是:两个或者多个执行单元(线程/进程)请求受限资源碰到了僵局,争持不下。
特征上表现为:
一号线程持有锁A,继续执行的过程尝试获取锁B;
二号线程持有锁B,继续执行过程尝试获取锁A。
这样两个线程就是互相僵持,不让步,谁也没法让步。
就像下面的代码一样:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/24 12:02 上午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : testthread_lock_really_deadlock.py
# @Project : hello
import threading
import time
xuewei_account = 100
lock_01 = threading.Lock()
lock_02 = threading.Lock()
# amount为负数即是转出金额
def transfer1(money):
print("%s - try to acquire lock_01" % threading.current_thread().name)
lock_01.acquire()
print("%s - acquired lock_01 transfer now" % threading.current_thread().name)
time.sleep(3)
print("%s - try to acquire lock_02" % threading.current_thread().name)
lock_02.acquire()
print("%s - acquired lock_02 transfer now" % threading.current_thread().name)
print("transfer done")
lock_02.release()
lock_01.release()
print("release")
# amount为负数即是转出金额
def transfer2(money):
print("%s - try to acquire lock_02" % threading.current_thread().name)
lock_02.acquire()
print("%s - acquired lock_02 transfer now" % threading.current_thread().name)
time.sleep(3)
print("%s - try to acquire lock_01" % threading.current_thread().name)
lock_01.acquire()
print("%s - acquired lock_01 transfer now" % threading.current_thread().name)
print("transfer done")
lock_01.release()
lock_02.release()
print("release")
threading.Thread(name="这个线程%s要请求锁" % 1, target=lambda: transfer1(100)).start()
threading.Thread(name="这个线程%s要请求锁" % 2, target=lambda: transfer2(-100)).start()
print("-" * 16)
print("学委账户余额:", xuewei_account)
运行效果如下:
我们可以看到,两个线程一分别获取了lock_01和lock_02之后,
尝试获取lock_02 和 lock_01,然后就不继续运行了,没错,这就是死锁。
然而,主线程 则在一旁围观,他们锁了,没碍着主线程。主线程无欲无求,继续干着活,编写这代码,默默地输出xuewei_account余额。
总结
这篇小短文,简单介绍了一下死锁,展示了一下。
死锁是发生在两个线程之间的。
具体一点,这是死锁发生的4个必要条件:
- 互斥条件:资源任意时刻只有一个持有者;仅当资源持有者释放,资源才可再次被申请
- 不可剥夺条件:资源持有者保持锁的唯一话语权,持有者不释放资源,其他人只能干等
- 请求与保持条件:资源申请者保持对已持有锁的锁定状态(吃碗看锅)
- 循环等待条件:两个或者以上竞争者头尾相接等待资源,A->B->A如此循环等待
所以,一个线程如果发生了(代码不小心写了个死循环acquire同一个锁),那不算死锁(不满足学术定义)
简单理解可以是,”单身狗谈何爱情“,死锁是发生在两个或者更多资源竞争者之间的。
喜欢Python的朋友,请关注学委的 Python基础专栏 or Python入门到精通大专栏
持续学习持续开发,我是雷学委!
编程很有趣,关键是把技术搞透彻讲明白。
欢迎关注微信,点赞支持收藏!
以上是关于Python的线程16 一分钟写个死锁,单身狗谈何爱情的主要内容,如果未能解决你的问题,请参考以下文章