python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁
ps:python解释器" title="python解释器">python解释器有很多种,最常见的就是C python解释器
GIL全局解释器锁:
GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全
用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程无法实现并行但是可以实现并发)
GIL的存在是因为C python解释器的内存管理不是线程安全的
垃圾回收机制:
1、引用计数
2、标记清除
3、分代回收
研究python 的多线程是否有用的话需要分情况讨论:
同时执行四个任务 计算密集型:10s
# 计算密集型from multiprocessing import Process
from threading import Thread
#mport os,time
def work():
res=0
for i in range(100000000):
res*=i
if __name__ == '__main__':
l=[]
print(os.cpu_count()) # 本机为6核
start=time.time()
for i in range(6):
# p=Process(target=work) #耗时 4.732933044433594
p=Thread(target=work) #耗时 22.83087730407715
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
单核情况下:
开线程更节省资源
多核情况下:
开进程:10s
开线程:40s
同时执行四个IO密集型任务
# IO密集型from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
time.sleep(2)
if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为6核
start=time.time()
for i in range(4000):
p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在创建进程上
# p=Thread(target=work) #耗时2.051966667175293s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
单核:开线程更省资源
多核:开线程更省资源
Event事件:
from threading import Event,Threadimport time
# 先生成一个event对象
e = Event()
def light():
print('红灯正亮着')
time.sleep(3)
e.set() # 发信号
print('绿灯亮了')
def car(name):
print('%s正在等红灯'%name)
e.wait() # 等待信号
print('%s加油门飙车了'%name)
t = Thread(target=light)
t.start()
for i in range(10):
t = Thread(target=car,args=('伞兵%s'%i,))
t.start()
信号量:在不同的领域中,对应不同的知识点
互斥锁:一个厕所(一个坑)
信号量:公共厕所(多个坑位)
from threading import Semaphore,Threadimport time
import random
sm = Semaphore(5) # 造了一个含有五个的坑位的公共厕所
def task(name):
sm.acquire()
print('%s占了一个坑位'%name)
time.sleep(random.randint(1,3))
sm.release()
for i in range(40):
t = Thread(target=task,args=(i,))
t.start()
死锁:
RLock可以被第一个抢到锁的人连续的acquire和release
每acquire一次锁身上的计数就加1
每release一次锁身上的计数就减1
只要是锁的计数不为0 其他人都不能抢
class MyThread(Thread):def run(self): # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('%s抢到了A锁'%self.name) # self.name等价于current_thread().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(10):
t = MyThread()
t.start()
递归锁:
import threadingclass MyThread(threading.Thread):
def run(self):
global n1, n2
lock.acquire() # 加锁
n1 += 1
print(self.name + ' set n1 to ' + str(n1))
lock.acquire() # 再次加锁
n2 += n1
print(self.name + ' set n2 to ' + str(n2))
lock.release()
lock.release()
n1, n2 = 0, 0
lock = threading.RLock()
if __name__ == '__main__':
thread_list = []
for i in range(5):
t = MyThread()
t.start()
thread_list.append(t)
for t in thread_list:
t.join()
print('final num:%d ,%d' % (n1, n2))
以上是 python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁 的全部内容, 来源链接: utcz.com/z/389516.html