RLock(递归锁)
import threading, time
def run1():
print("grab the first part data")
lock.acquire()#进入大门后的一间屋子
global num
num += 1
lock.release()#退出这间屋子
return num def run2():
print("grab the second part data")
lock.acquire()#进入大门后的另一间屋子,和上个屋子平行
global num2
num2 += 1
lock.release()#退出这间屋子
return num2 def run3():
lock.acquire()#第一道门,大门
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res, res2) if __name__ == '__main__': num, num2 = 0, 0
lock = threading.Lock()
for i in range(10):
t = threading.Thread(target=run3)
t.start()
#一共11个线程
while threading.active_count() != 1:
print(threading.active_count())
else:#只剩一个线程了,表示所有子线程执行完毕
print('----all threads done---')
print(num, num2)
结果:
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
11
一直执行,不停的打印11......,锁死了,怎么办?其实是各个门之间的钥匙混了,所以打不开锁了,锁死了,需要以下操作才能解决。
RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
import threading, time
def run1():
print("grab the first part data")
lock.acquire()
global num
num += 1
lock.release()
return num def run2():
print("grab the second part data")
lock.acquire()
global num2
num2 += 1
lock.release()
return num2 def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res, res2) if __name__ == '__main__': num, num2 = 0, 0
lock = threading.RLock()#改为递归锁
for i in range(10):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num, num2)
结果:
D:\Anaconda3\python.exe C:/Users/Administrator/Desktop/py_work/lib/aa.py
grab the first part data
--------between run1 and run2-----
grab the second part data
1 1
grab the first part data
--------between run1 and run2-----
grab the second part data
2 2
grab the first part data
--------between run1 and run2-----
grab the second part data
3 3
grab the first part data
--------between run1 and run2-----
grab the second part data
4 4
grab the first part data
--------between run1 and run2-----
grab the second part data
5 5
grab the first part data
--------between run1 and run2-----
grab the second part data
6 6
grab the first part data
--------between run1 and run2-----
grab the second part data
7 7
grab the first part data
--------between run1 and run2-----
grab the second part data
8 8
grab the first part data
--------between run1 and run2-----
grab the second part data
9 9
grab the first part data
--------between run1 and run2-----
grab the second part data
10 10
----all threads done---
10 10 Process finished with exit code 0
概念总结:
死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
那么怎么解决死锁现象呢?
解决方法,递归锁:在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁。
threading.Lock和threading.RLock区别:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
RLock(递归锁)的更多相关文章
- 死锁的原因及解决办法RLock递归锁
死锁 说到死锁,可以讲一个科学家吃面的问题: 有几个科学家在一张桌子旁,桌子上只有一把筷子和一碗面,我们将面和筷子都加锁.这是可能会导致一个科学家抢到面,另一个科学家抢到筷子,这是就全部阻塞了,这就是 ...
- setdeamon 设置 线程为守护线程, (lock线程锁, BoundedSemaphore,rlock递归锁 ) 三种锁
1.setdeamon 当主程序执行完时,子程序自动被销毁 ,内存自动被收回 例一: import threading, time def run(n): print('run %s'%n) time ...
- Python 递归锁
import time from threading import Thread, Lock, RLock def f1(locA, locB): # print('xxxx') # time.sle ...
- python 线程(创建2种方式,锁,死锁,递归锁,GIL锁,守护进程)
###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位 线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个 ...
- 6-[多线程]-互斥锁、GIL、死锁、递归锁、信号量
1.互斥锁(排他锁) (1)不加锁的情况下 并发控制问题:多个事务并发执行,可能产生操作冲突,出现下面的3种情况 丢失修改错误 不能重复读错误 读脏数据错误 # mutex from threadin ...
- 线程、进程、daemon、GIL锁、线程锁、递归锁、信号量、计时器、事件、队列、多进程
# 本文代码基于Python3 什么是进程? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行 ...
- Python死锁与递归锁
Lock() 互斥锁会导致死锁,用RLock()递归锁代替. 递归锁:可以连续acquire多次,每acquire一次计数器+1(无论acquire的是哪个锁),只有计数为0才能被acquire mu ...
- 线程全局修改、死锁、递归锁、信号量、GIL以及多进程和多线程的比较
线程全局修改 x = 100 def func1(): global x print(x) changex() print(x) def changex(): global x x = 50 func ...
- python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)
9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕详细解释:1.主 ...
- python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03
目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...
随机推荐
- swift日期操作
简介:本文将介绍一些关于swift中对于日期的格式化与获取,支持swift4.0 extension Date { //格式化日期 func getDateString() -> String{ ...
- 解决“System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本”
问题描述:远程访问该数据库(客户端同样是Oracle11g)提示“System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本”. 解决的办法: 1.一定要关闭Win ...
- 201621123016 《Java程序设计》第八周学习总结
1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 ArrayList在调用contains方法时会调用indexOf方法得到 ...
- CodeForces 761C 【DP】
总结:能这么DP就这么写! 多练位运算标记. #include<bits/stdc++.h> using namespace::std; const int N=55; const int ...
- Oculus Rift, HTC Vive, SONY PSVR的全面对比
http://blog.csdn.net/xoyojank/article/details/50927572 这次有幸参加了GDC 2016, 终于把三大设备体验了个遍, 也试玩了很多不错的VR游戏. ...
- PHP保留小数的相关方法
结合一下网上的例子 $num = 10.4567; //第一种:利用round()对浮点数进行四舍五入 但是这个如果没有两位小数也不会"两位精度" echo round($num, ...
- bzoj1145[CTSC2008]图腾
传送门 虽然是远古时期的ctsc,但是果然还是ctsc啊 前置芝士:树状数组 这个题最开始的思路很好想,由于之前写过一个类似处理的题,所以这个题我一开始就想到了思路. 首先,我们可以尝试讲图腾表示为x ...
- IDE工具、文本编辑器的列块编辑模式
前言 有时候需要对若干列进行一样的操作,比如在前一百行数据的最前边加上一样的字符,这时候可以通过列块编辑模式来快捷地实现这个效果.在列块编辑模式下,被选定的区域内的所有字符会被替换成你之后输入的字符. ...
- PostgreSQL - pgAdmin4远程连接数据库
前言 PostgreSQL在安装的时候自带的pgAdmin这个可视化工具,自从将PostgreSQL9升级到了10版本后,自带的pgAdmin也从3升级到了4版本.pgAdmin4的变化非常巨大,刚接 ...
- 虚拟机无法分配内存 virtual memory exhausted: Cannot allocate memory
1.内存交换空间(swap)的构建 安装Linux时一定需要的两个分区:根目录和swap(内存交换空间). swap的功能:在应付物理内存不足的情况下所造成的内存扩展记录的功能. 物理内存不足的时候, ...