锁,Event,semaphore
- GIL:全局解释锁:无论开启多少个线程,同一时刻只允许执行一个线程运行(解释器级别,保护数据)
锁:两种状态,锁定和未锁定,仅支持两个函数,获得锁和释放锁
多线程抢夺锁时,当某个线程获得锁了,其他的锁都会被阻塞,直到这个线程释放锁后,其他线程才可以再抢夺锁,注意线程抢夺锁是没有顺序的
同步锁:Lock,与GIL不同,它是用户层面上的,由用户自定义
- import threading
- import time
- def sub():
- global num
- # 加上一个锁,使得本来并发的变成串行,用来保护自己的数据不被其他的线程拿到
- lock.acquire() #获得锁
- temp = num
- time.sleep(0.01) #当阻碍时间较长时,其他的线程可能也会拿到这个数据
- num = temp - 1
- lock.release() #释放锁
- num = 100
- l = []
- lock = threading.Lock() #声明一个锁
- for i in range(100):
- t = threading.Thread(target=sub)
- t.start()
- l.append(t)
- for t in l:
- t.join()
- print(num)
- 死锁:当存在多线程时,双方都在等对方释放锁,产生死锁,当无外力作用时,程序将无法推进下去
递归锁:RLock内部维护着一个counter,每次acquire都会使得counter + 1 ,每release一次counter - 1,
当counter大于0时,只能有一个线程可以获得这个锁,只有等于0时,其他线程才能获得这个锁
- import threading
- import time
- class MyThread(threading.Thread):
- def action1(self):
- t1.acquire()
- print(self.name,"got t1",time.ctime)
- time.sleep(2)
- t2.acquire()
- print(self.name,"got t2",time.ctime)
- time.sleep(2)
- t2.release()
- t1.release()
- def action2(self):
- t2.acquire()
- print(self.name, "got t2", time.ctime)
- time.sleep(2)
- t1.acquire()
- print(self.name, "got t1", time.ctime)
- time.sleep(2)
- t1.release()
- t2.release()
- def run(self):
- self.action1()
- self.action2()
- if __name__ == '__main__':
- t1 = threading.Lock()
- t2 = threading.Lock()
- L = []
- for i in range(5):
- t = MyThread()
- t.start()
- L.append(t)
- for t in L:
- t.join()
- print("end...")
解决产生死锁:使用递归锁,t1,t2的锁声明改为 threading.RLock()
同步条件:Event
- #创建Event对象
event = threading.Event- 3个方法
#a client thread wait for the flag to be set
event.wait()- #a server thread can set or reset it
event.set()
event.clear()
使用规则
if the flag is set , the wait method doesn't do anything
if the flag is cleared ,the wait block until it becomes set again
any number of threads may wait for the same event
- import threading,time
- class Boss(threading.Thread):
- def run(self):
- print("BOSS:everybody works overtime tonight。")
- print(event.isSet())
- event.set()
- time.sleep(5)
- print("BOSS:can leave work。")
- print(event.isSet())
- event.set()
- class Worker(threading.Thread):
- def run(self):
- event.wait() #当Event没有set时,wait方法被调用,阻塞,当Event被set后,这个wait方法就相当于pass
- print("Worker:ah……life is bitter!")
- time.sleep(1)
- event.clear()
- event.wait()
- print("Worker:OhYeah!")
- if __name__=="__main__":
- event=threading.Event()
- threads=[]
- for i in range(5):
- threads.append(Worker())
- threads.append(Boss())
- for t in threads:
- t.start()
- for t in threads:
- t.join()
信号量:Semaphore
用来控制线程并发数,当同时并发的线程达到指定的最大数时,其他线程将会被阻塞
BoundedSemaphore或Semaphore内置一个计数器,当acquire()时 -1,当release()时 +1,
计数器不能小于0,当计数器等于0时,acquire()将线程阻塞同步至锁定状态,直到有线程release()释放
BoundedSemaphore和Semaphore的区别:BoundedSemaphore在调用release()检测计数器是否超过设定值,达到抛出一个异常
- import threading,time
- class myThread(threading.Thread):
- def run(self):
- if semaphore.acquire():
- print(self.name)
- time.sleep(5)
- semaphore.release()
- if __name__=="__main__":
- semaphore=threading.Semaphore(5) #设置可以同时有几个线程并发
- thrs=[]
- for i in range(100):
- thrs.append(myThread())
- for t in thrs:
- t.start()
锁,Event,semaphore的更多相关文章
- 【分布式锁】07-Zookeeper实现分布式锁:Semaphore、读写锁实现原理
前言 前面已经讲解了Zookeeper可重入锁的实现原理,自己对分布式锁也有了更深的认知. 我在公众号中发了一个疑问,相比于Redis来说,Zookeeper的实现方式要更好一些,即便Redis作者实 ...
- Day12- Python基础12 线程、GIL、Lock锁、RLock锁、Semaphore锁、同步条件event
http://www.cnblogs.com/yuanchenqi/articles/6248025.html 博客地址 本节内容: 1:进程和线程的说明 2:线程的两种调用方式 3:threadi ...
- 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁
一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...
- 带你看看Java的锁(二)-Semaphore
前言 简介 Semaphore 中文称信号量,它和ReentrantLock 有所区别,ReentrantLock是排他的,也就是只能允许一个线程拥有资源,Semaphore是共享的,它允许多个线程同 ...
- 同步锁 死锁与递归锁 信号量 线程queue event事件
二个需要注意的点: 1 线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock任然没有被释放则阻塞,即便是拿到执行权限GIL也要 ...
- Python之网路编程之死锁,递归锁,信号量,Event事件,线程Queue
一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...
- Python 中Semaphore 信号量对象、Event事件、Condition
Semaphore 信号量对象 信号量是一个更高级的锁机制.信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞.这允许了多个线程可以同时访问相同的代码区 ...
- python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享
Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...
- python多线程锁lock/Rlock/BoundedSemaphore/Condition/Event
import time import threading lock = threading.RLock() n = 10 def task(arg): # 加锁,此区域的代码同一时刻只能有一个线程执行 ...
- 34、锁问题与线程queue
上一篇随笔我们学了全局解释器锁,前面也学了互斥锁,今天学习一些与锁相关的点,例如递归锁,信号量,Event,还会学习我们已经很熟悉的队列,不过这次的队列是作为一个模块出现的. 一.同步锁 1.join ...
随机推荐
- Oracle数据库备份还原
导出备份的命令: 开始->运行->cmd->exp username/password@tns_name file=d:\backup.dmp 导入备份的命令: 开始->运行- ...
- php中用生成的公钥、私钥进行加密解密
$private_key = '-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDpoODVtnSztGyb//p+g/Ob36jb3jzWzS2qovOjp ...
- linux下插入U盘自动挂载后,用C获取其挂载点(cat /proc/mounts)
现在已经能够通过libudev获取U盘插入时它的节点名(通过函数udev_device_get_devnode()),是/dev/sdb1 我现在的做法是读取/proc/mounts文件,找到有/de ...
- htonl(),htons(),ntohl(),ntons()--大小端模式转换函数
不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian). 大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处. 小端模 ...
- SSH port forwarding: bind: Cannot assign requested address
https://www.electricmonk.nl/log/2014/09/24/ssh-port-forwarding-bind-cannot-assign-requested-address/
- Django学习之Cookie和Session
一.Cookie 1.Cookie的由来 2.什么是Cookie 3.Cookie的原理 4.查看Cookie 二.Django中操作Cookie 1.获取Cookie 2.设置Cookie 3.删除 ...
- 【MAC】 命令行解压缩 rar 文件
使用Mac解压rar文件很简单,总共分2步.step1:安装解压工具,step2:解压 1.使用Homebrew安装unrar brew install unrar 2.cd到rar文件的目录下,然后 ...
- Vue知识整理13:表单输入绑定(v-model)
text:将输入框等表单,通过data变量实现数据绑定. textbox:数据绑定 3.checkbox和redio组件: 注意:data数据变量中,checkbox有可能会有多个结果,所以用数组: ...
- nacos 发布配置
server 保留 2 份配置文件,一份在 mysql,一份在本地磁盘,同时在内存中缓存配置文件的 md5 值.当客户端获取配置时,server 直接返回本地磁盘文件,使用的是 sendFile ap ...
- Binary-to-text ecoding:
binary to Text ecoding是指将二进制数据转换成可打印的符号 如果传输channel 不允许二进制数据(如email) 一般使用Base64 ASCII 标准使用128位来表示字母数 ...