多线程——GIL信号量递归锁
Posted king-home
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程——GIL信号量递归锁相关的知识,希望对你有一定的参考价值。
互斥锁
1、什么是GIL(global interpreter lock)?
GIL是一个互斥锁:保证数据的安全(牺牲效率来获取数据的安全),阻止同一个进程内的多线=线程同时执行(不能并行但是能实现并发)
2、为什么会有GIL?
由于cpython解释器的内存管理不是线程安全的(垃圾回收机制的存在)
同一进程想的多线程不能实现并行但是可以实现并发,不同进程下可以实现并行
问题:Python多线程是不是就没有用:
举个例子: 四个任务:计算密集任务,每个任务10s 单核情况下: 多线程好点,消耗资源少,速度快 多核情况下: 开四个进程,10s多点 开四个线程,40s多点 四个任务:IO密集任务,每个任务10s 单核情况下: 多线程好点 多核情况下: 多线程好点 总结:多线程和多进程都有自己的优点和缺点,根据项目需求合理选择 对于不同的数据要加不同的锁进行,GIL不能保证数据的安全,他只针对线程。保证同一个进程下的多个线程是安全的
3、死锁和递归锁
自定义锁(Lock):自定义锁必须一次acquire 必须对应一次release,不能连续需acquire
递归锁(RLock):可以连续acquire,每acquire一次,计数加1:针对的是第一抢到的人
from threading import Thread,Lock,RLock import time """ 自定义锁一次acquire必须对应一次release,不能连续acquire 递归锁可以连续的acquire,每acquire一次计数加一:针对的是第一个抢到我的人 """ import random # # mutexA = Lock() # mutexB = Lock() mutexA = mutexB = RLock() # 抢锁之后会有一个计数 抢一次计数加一 针对的是第一个抢到我的人 class MyThead(Thread): def run(self): self.func1() self.func2() def func1(self): mutexA.acquire() print(‘%s 抢到A锁了‘%self.name) mutexB.acquire() print(‘%s 抢到B锁了‘ % self.name) mutexB.release() print(‘%s 释放了B锁‘%self.name) mutexA.release() print(‘%s 释放了A锁‘%self.name) def func2(self): mutexB.acquire() print(‘%s 抢到了B锁‘%self.name) time.sleep(1) mutexA.acquire() print(‘%s 抢到A锁了‘ % self.name) mutexA.release() print(‘%s 释放了A锁‘ % self.name) mutexB.release() print(‘%s 释放了B锁‘ % self.name) for i in range(100): t = MyThead() t.start()
4、信号量
sm = Semaphore()
from threading import Thread,Semaphore import time import random sm = Semaphore(5) # 五个厕所五把锁 # 跟你普通的互斥锁区别在于,普通的互斥锁是独立卫生间,所有人抢一把锁 # 信号量 公共卫生间 有多个坑,所有人抢多把锁 def task(name): sm.acquire() print(‘%s正在蹲坑‘%name) # 模拟蹲坑耗时 time.sleep(random.randint(1,5)) sm.release() if __name__ == ‘__main__‘: for i in range(20): t = Thread(target=task,args=(‘伞兵%s号‘%i,)) t.start()
5、线程queue:
queue分为三类:
1.普通q:q=queue.Queue(3)
2.先进后出:q = queue.LifoQueue(5)
3.优先级q:q = queue.PriorityQueue()
#普通q # q=queue.Queue(3) # q.put(1) # q.put(2) # q.put(3) # print(q.get()) # print(q.get()) # print(q.get()) # 先进后出q # q = queue.LifoQueue(5) # q.put(1) # q.put(2) # q.put(3) # q.put(4) # print(q.get()) # 优先级q # q = queue.PriorityQueue() # q.put((10,‘a‘)) # q.put((-1,‘b‘)) # q.put((100,‘c‘)) # print(q.get()) # print(q.get()) # print(q.get())
以上是关于多线程——GIL信号量递归锁的主要内容,如果未能解决你的问题,请参考以下文章
Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池
GIL全局解释器锁死锁递归锁信号量Event事件线程Queue