# 官方文档对GIL的解释
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
"""
1.在CPython解释器中存在全局解释器锁简称GIL
python解释器有很多类型
CPython JPython PYPython(常见的是CPython解释器)
2.GIL本质也是一把互斥锁,用来阻止同一个进程内多个线程同时执行(重要)
3.GIL的存在是因为CPython解释器中内存管理不是线程安全的(垃圾回收机制)
垃圾回收机制:
引用计数、标记清楚、分代回收
"""
验证GIL的存在
from threading import Thread
num = 100
def task():
global num
num -= 1
t_list = [] # 定义一个列表
for i in range(100):
t = Thread(target=task)
t.start() # 创建子进程
t_list.append(t) # 子进程添加列表里面
for t in t_list:
t.join() # 主进程等子进程结束才执行,这样全部子进程结束才会打印num
print(num)
死锁现象
from threading import Thread, Lock
import time
mutexA = Lock() # 产生一把锁A
mutexB = Lock() # 产生一把锁B
class MyThreading(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print(f'{self.name}抢到了A锁')
mutexB.acquire()
print(f'{self.name}抢到了B锁')
mutexB.release()
print(f'{self.name}释放了B锁')
mutexA.release()
print(f'{self.name}释放了A锁')
def func2(self):
mutexB.acquire()
print(f'{self.name}抢到了B锁')
time.sleep(1)
mutexA.acquire()
print(f'{self.name}抢到了A锁')
mutexA.release()
print(f'{self.name}释放了A锁')
mutexB.release()
print(f'{self.name}释放了B锁')
for i in range(10):
obj = MyThreading()
obj.start()
"""
死锁产生原因:
多个线程同时产生,去抢锁A,这时只有一个线程抢到了锁A,其他线程需要排队,抢到锁A的线程才可以去抢锁B,这时候没有其他线程可以参与抢锁A与锁B,因为锁A还没有被释放,抢到了锁B的线程释放了锁B,但是其他线程因为锁A没有释放不能够抢,线程1执行函数func2,抢锁B,因为刚才锁B已经被释放,其他线程则其实有一个抢到了锁A,线程1碰到IO操作,CPU切换,抢到了锁A的执行但是下一步要抢锁B,而锁B在线程1手上,无法继续下一步,等线程1O操作,他要抢锁A,而锁A在其他线程手中也无法继续下一步,这时候就会产生死锁现象
"""
信号量
在python并发编程中信号量相当于多把互斥锁
from threading import Thread, Semaphore
import time
import random
sp = Semaphore(5) # 一次性产生5把锁
class Mythread(Thread):
def run(self):
sp.acquire() # 加锁
print(self.name)
time.sleep(random.randint(1,3)) # 模拟延迟
sp.release() # 释放锁
for i in range(20):
t = Mythread()
t.start()
"""
信号量可以理解问,我们同时产生5把锁让线程去抢,这时候就会有5个线程去抢到5把锁,然后去执行,有线程执行完毕把锁的位置让出来其他线程去抢到空余的锁执行
"""
event事件
from threading import Thread, Event
import time
event = Event() # 类似造了一个红绿灯
def light():
print('红灯亮着 所有人不能动')
time.sleep(3)
print('绿灯亮了 油门踩到底!冲冲冲!!!')
event.set()
def car(name):
print(f'{name}正在等红灯')
event.wait() # event事件表示,会在这里等待执行到event.set()执行结束才会执行
print(f'{name}飙车了')
t = Thread(target=light)
t.start()
for i in range(10):
t = Thread(target=car, args=('熊猫PRO%s' % i,))
t.start()
"""
event是一个组合使用的,在执行过程中到event.wait()这里会停止,等待程序执行event.set()执行以后才会执行后面的
"""