1.GIL
是一个全局解释器锁 ,是一种互斥锁
为什么需要GIL:因为一个python.exe进程中只有一分解释器,如果这个进程开启了多个线程都要执行代码
多线程之间要竞争解释器,一旦竞争就有可能出现问题
带来的问题:同一时间只有一个线程可以访问解释器
好处:保证了多线程的数据完全
thread-safe 线程安全的 多个线程同时访问也不会出问题
not thread-safe 非线程安全的 多个线程同时访问可能会出问题 (加锁)
默认情况下一个进程只有一个线程 是不会出现问题的 ,但是不要忘记还有GC线程
一旦出现多个线程就可能出问题 ,所以当初就简单粗暴的加上了GIL锁
那么多线程是不是完全没有意义?
由于有GIL的存在 即使有多个CPU 也不能真正的并行
有三个任务 三个任务要并发执行 使效率最高
1.多进程
2.同一个进程下多线程
只有一个CPU
如果3个任务都要等待IO
如果是采用方案1: 由于IO的时间较长 不仅不能提高效率 反而无谓的增加了系统开销
方案2 更好
有三个CPU
如果是采用方案1 并且三个任务都没有IO操作: 开启三个进程 并行的来执行 效率更高
如果是采用方案2 并且三个任务都没有IO操作: 开三个线程 必须串行执行 所以效率比进程更低
应用程序分为两种
1.IO密集型 IO操作较多 纯计算较少 采用多线程
2.计算密集型 计算操作较多 IO较少 采用多进程
IO密集型任务:
from multiprocessing import Process
from threading import Thread,enumerate,current_thread
import time
def task():
with open("xxx","rt",encoding="utf-8") as f:
f.read()
if __name__ == '__main__':
start = time.time()
for i in range(100):
Thread(target=task).start()
# enumerate是所有的线程
for t in enumerate():
if t != current_thread():
t.join()
# ps = []
# for i in range(100):
# p = Process(target=task)
# p.start()
# ps.append(p)
#
# for p in ps:
# p.join()
print(time.time()-start)
计算密集型任务:
from multiprocessing import Process
from threading import Thread,enumerate,current_thread
import time
def task():
a = 1
for i in range(10000000):
a += 1
if __name__ == '__main__':
start = time.time()
# 采用多线程
# for i in range(10):
# Thread(target=task).start()
#
# # enumerate是所有的线程
# for t in enumerate():
# if t != current_thread():
# t.join()
ps = []
for i in range(10):
p = Process(target=task)
p.start()
ps.append(p)
for p in ps:
p.join()
print(time.time()-start)
应用场景:
TCP程序 应该采用多线程
纯计算 例如人脸识别 语音识别等 采取多进程
GIL
是什么 为什么出现 如何解决其带来的效率问题
既然已经有锁了 还需要自己加锁吗?
什么情况需要自己加锁 当多个线程需要共享一个不属于解释器的资源时 必须要自己加
不用加锁的例子: 多个线程要并发修改某一个变量数据