递归锁

一把大锁在加一把小锁。

import threading
import 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() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num, num2)

过程分享:
1、启动10个线程,每个线程都执行run3。

2、run3中先加了一个锁,然后执行run1。

3、run1中也加了一个锁,计算完成后解锁返回数据。执行run2。

4、run2中同样加了一个锁,计算完成后解锁打印run1,run2返回值。

5、最后打印num1、num2。

需要注意的是在执行过程中是有两把锁的,一个run3,一个run1或者run2。

运行结果:

11
11
11
11
11
11
11
11
# 程序进入死循环

死循环的原因是解锁的时候 钥匙拿错了导致进程退不出来,解决死锁就是要使用递归锁。

threading.Lock() 改为 threading.RLock()

import threading
import 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(1):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num, num2)

运行结果

grab the first part data
--------between run1 and run2-----
grab the second part data
1 1
----all threads done---
1 1

实现原理:

解锁的时候找对应的钥匙。

信号量

互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。简单的说就是互斥锁同一时间只能要一个线程修改数据,信号量同一时间可以让多个线程修改数据。信号量可以挂多吧锁。

import threading,time

def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s\n" %n)
semaphore.release() if __name__ == '__main__': num= 0
semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run,args=(i,))
t.start() while threading.active_count() != 1:
pass #print threading.active_count()
else:
print('----all threads done---')
print(num)

每一个进程结束了就重新添加一个新的进去。

python递归锁与信号量的更多相关文章

  1. Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池

    Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...

  2. 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue

    GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...

  3. python并发编程之多线程2------------死锁与递归锁,信号量等

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  4. python并发编程之多线程2---(死锁与递归锁,信号量等)

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  5. Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)

    1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...

  6. python并发编程之多线程2死锁与递归锁,信号量等

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 这些永远在互相等待的进程称为死锁进程 如下就是死锁 ...

  7. Python 36 死锁现象和递归锁、信号量、Event事件、线程queue

    一:死锁现象和递归锁 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远 ...

  8. Python之路(第四十四篇)线程同步锁、死锁、递归锁、信号量

    在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock ...

  9. python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)

    9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕​详细解释:1.主 ...

随机推荐

  1. Linux 安装 Djiango

    yum 安装方法 以下安装位于 Centos Linux 环境下安装,如果是你的 Linux 系统是 ubuntu 请使用 apt-get 命令. 默认情况下 Linux 环境已经支持了Python. ...

  2. 认识HTML中文本、图片、链接标签和路径

    前端之HTML.CSS(一) 开发工具 编辑器 Dreamware.Sublime.Visual Studio Code.WebStorm 浏览器 Chrome.IE(Edge).Safari.Fir ...

  3. hash & heap - 20181023 - 20181026

    129. Rehashing /** * Definition for ListNode * public class ListNode { * int val; * ListNode next; * ...

  4. 数据插入INSERT

    一.INSERT SELECT :将查询的数据直接插入 特点: 1.一次性插入所有查询出来的数据. 2.数据原子性,有一个失败全部失败. 3.没有指定的列加默认值或NULL,都没有就报错. 二.INS ...

  5. Python学习 day07

    一.关于解决问题的思路 1.删除列表中索引为单数的元素. 别人的思路: 利用切片 li = [11, 22, 33, 44, 55] li = li[::2] print(li) 思考:虽然学了pyt ...

  6. Oracle DG --检查

    检查DG是否同步 01,  查看主备可切换状态 select switchover_status from v$database;select db_unique_name,open_mode,dat ...

  7. spring 3.0 @ResponseBody注解返回中文问号乱码解决办法

    前几天给公司做项目,很久没接触java项目的我,遇到了一个问题,就是我在利用异步到控制器中查询,然后返回jaon字符串到前台,字符串中包含中文,于是我直接用了@ResponseBody注解,来返回到前 ...

  8. Win7 x86内核调试与TP反调试的研究

    参考  这两天对某P双机调试的学习及成果 ,非常好的一篇分析贴. 本文在Win7 x86下的分析,在虚拟机中以/DEBUG模式启动TP游戏,系统会自动重启. 0x01 内核调试全局变量  根据软件调试 ...

  9. 【Linux相识相知】rpm包管理

    我们日常在使用Windows的时候,如果要安装某个软件,最简单的方法就是在程序包的官网直接下载软件包到本地,一般是以.exe或者.msi格式的文件,然后一直下一步下一步就能安装成功了,但是在使用lin ...

  10. GridView .net访问

    HTML code <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=&qu ...