day36

今日总结:

GIL 锁:   全局解释器锁
线程的安全问题:就是几个线程同一时间去抢占资源问题,这样就会导致数据错乱
GIL锁只存在在cpython中,内置的自带锁,每个线程都自带

造成的影响
# 首先必须明确执行一个py文件,分为三个步骤
1,从硬盘加载python解释器到内存
2,从硬盘加载py文件到内存
3,解释器解析py文件内容,交给cpu执行
其次要明确的是每当执行一个py文件,就会立即启动一个Python解释器,
py文件中的内容本质是字符串,只有在被解释器解释时,才具备语法意义,解释器会将当前代代码解释给系统能识别的执行的代码
开启子线程时,给子线程指定了一个target表示该子线程要处理的任务即要执行的代码。代码要执行则必须交由解释器,
即多个线程之间就需要共享解释器,为了避免共享带来的数据竞争问题,于是就给解释器加上了互斥锁
由于互斥锁的特性,程序串行,保证数据安全,降低执行效率吗,GIL将使得程序效率降低
为什么需要GIL
在使用Python中进行编程时,程序员无需参与内存的管理工作,这是因为Python有自带的内存管理机制,简称GC
有了GIL后,多个线程将不可能在同一时间使用解释器,从而保证了解释器的数据安全。
GIL的加锁与解锁时机:
当前线程调用解释器时立即进行加锁
解锁: 当前线程遇到IO操作时解锁
当前线程执行时间超出设置的时间时释放

GIL 的优点:
保证了CPython中的内存管理是线程安全的
的缺点:
互斥锁的特性使得多线程无法运行
总结:
Cpython中IO密集任务应该采用多线程,计算密集型因该采用多进程
在io 密集型多用于多线程 速度快 计算密集型多采用进程,速度快

GIL 保护的是解释器级别的数据安全你,比如对象的应用技术,垃圾分代数据等等
对于程序中自己定义的数据则没有任何的保护,所以当程序中出现了共享自定义数据是就需要自己加锁

进程池和线程池
池 表示一个容器 ,本质上就是一个存储进程或线程的列表
池子中存储的如果是IO密集型任务使用线程池
如果是计算密集任务则用进程池
from concurrent.futures import ProcessPoolExecutor
import time, os

# 创建进程池,指定最大进程数为3,此时不会创建进程,不指定数量时,默认为cpu的 -数

pool = ProcessPoolExecutor(3)


def task():
time.sleep(1)
print(os.getpid(), "working")


if __name__ == '__main__':
for i in range(10):
pool.submit(task) # 提交任务时立即创建进程

# 任务执行完成后也不会立即销毁进程
time.sleep(2)
for i in range(10):
pool.submit(task) # 再有新任务时,直接使用之前已经创建好的进程来执行

# 线程池的使用
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

from threading import current_thread, active_count
import time,os
# 创建线程池,指定最大线程数为3 ,此时不会创建线程,不指定数量时,默认为CPU 核数*5
pool= ThreadPoolExecutor(3)
print(active_count()) #只有一个主线程
def task():
time.sleep(1)
print(current_thread().name,"working")
if __name__ == '__main__':
for i in range(10):
pool.submit(task) #第一次提交任务时立即创建线程
time.sleep(2)
for i in range(10):
pool.submit(task) #再有新任务时直接使用之前已经创建好的线程来执行
待续:同步异步
原文地址:https://www.cnblogs.com/Fzhiyuan/p/10982393.html