1 为什么有了gil锁还要互斥锁
-并发和并行
-不能控制什么时候释放gil锁
-gil锁不能锁住共享资源
# 1 GIL 本身就是大的互斥锁
# 2 同一个进程下,资源是共享的----》多条线程可以操作同一个变量
# 3 多个线程操作同一个变量,就会出现数据安全问题
# 4 临界区:指一段代码或一段程序片段,需要在同一时间只能被一个线程执行---》多个线程操作临界区,会出现并发安全问题
# 错误的理解
-有了gil锁,同一时刻,只有一个线程执行,临界区代码,不也只有一个线程在执行吗?只有一个线程在执行,临界区就是安全的,不会出现数据错乱,所以没有必要再加互斥锁了
# 正确的解释:
gil锁释放不是我们控制的,比如在执行临界区中间,释放了,就会数据错乱问题
# 什么时候会释放gil锁?
-1 线程遇到io
-2 时间片轮转,时间片到了,就会自动切换
# 小案例解释
进程中有个变量a=0
临界区:a+=1
线程1要计算: a+=1
1 线程1 拿到gil
2 读取a=0
3 假设时间片到了,释放gil,释放cpu
4 等待下次被调度执行
10 轮到它了,获取gil锁
11 继续往下执行:计算a+1
12 把结果赋值给a ,a=1
13 释放gil锁
线程2要计算: a+=1
5 线程2获得了gil锁
6 读取a=0
7 计算a+1
8 把结果赋值给a ,a=1
9 释放gil锁
# 互斥锁保证数据安全
a=0
线程1要计算: a+=1
1 线程1 拿到gil
# 加锁
2 读取a=0
3 假设时间片到了,释放gil,释放cpu
4 等待下次被调度执行
7 轮到它了,获取gil锁
8 继续往下执行:计算a+1
9 把结果赋值给a ,a=1
10 释放gil锁
线程2要计算: a+=1
5 线程2获得了gil锁
#获取锁,获取不到
6 释放gil锁
11 获得gil锁
#加锁
12 读取a=0
13 计算a+1
14 把结果赋值给a ,a=1
15 释放锁
16 释放gil锁
# gil锁并不锁住临界区,临界区需要我们自己用互斥锁加锁
2. 进程,线程和协程
# 进程间通信需要使用管道,消息队列实现
# 线程间通信用什么?
# 协程会出现并发安全的问题吗?
###### 进程线程协程概念
# 进程:是资源分配的最小单位,一个应用程序运行起来,至少有一个进程,进程管理器中就可以看到一个个的进程
# 线程:是cpu调度,执行的最小单位,一个进程下至少有一个线程
# 协程:单线程下的并发,程序层面控制的任务切换
#####如果具体使用
# 开启多进程两种方式
-1 写一个类,继承Process,重写类的run方法---》实例化得到对象,对象.start 开启了进程
-2 通过Process类实例化得到一个对象,传入任务 ,调用对象.start 开启了进程
# 开启线程两种方式
-1 写一个类,继承Thread,重写类的run方法---》实例化得到对象,对象.start 开启了进程
-2 通过Thread类实例化得到一个对象,传入任务 ,调用对象.start 开启了进程
# 开启协程
- 早期之前:借助于第三方gevent,基于greelet写的
- async 和 await 关键字,不借助于第三方,开启协程 asyncio 包
-必须写在一个函数前, async def task()----》这个函数执行的结果是协程函数
-await 只要是io操作的代码,前面必须加 await
async def task1():
a+=1
time.sleep()
a+=10
async def task2():
a+=2
await 遇到io
a+=20
# 什么场景用过
-我一般遇到计算密集型的操作,我会开多进程,io密集型的操作,我一般开多线程
-闲来无事,爬别人数据,喜欢开多线程,爬虫io居多
-程序中,异步做一件事情,也可以开多线程
比如一个视图函数,异步的吧数据写的文件中
异步的发送钉钉通知
异步的发送邮件
-但实际上,在项目中,不需要我们开启进程线程,可以借助于第三方的框架比如celery就可以做异步的操作
而celery的worker,就是进程线程架构
-django框架,是支持并发,我们没有开启多进程和多线程,但是符合uwsgi的web服务器在进入djagno框架之前,开启了进程和线程来执行视图函数
# 拓展
不同进程下,资源是隔离的
进程间通信:IPC 机制
-消息队列
3 什么是鸭子类型
# 鸭子类型是python语言面向对象中的一个概念
#面向对象三大特性
-继承
-封装
-多态
# 多态和多态性?
-多态同一类事物的多种形态
# 现实生活中
-水:冰,水,水蒸气
-动物:人,狗,猫,猪
# 程序中
-Animal类:子类人,子类狗,子类猫
-多态性:不考虑对象具体类型的情况下使用对象
# 程序中
-len()内置函数---》传参数:字符串对象,列表对象,字典对象
-len(字典)
# 为什么能这样用?就是因为多态的存在
字符串,列表,字典----》属于同一类事物---》有长度的这一类事物
# 鸭子类型
-走路像鸭子,说话像鸭子,我们就可以叫它叫鸭子
-解释:鸭子类型是python面向对象中描述接口的一个概念,区分与其他编程语言,
比如java:实现类型,必须显示的继承这个类
而python:实现类型,遵循鸭子类型,不需要显示的继承一个类,只要类中有对应的属性跟方法,我们就称这几个类的对象为同一种类型
网友评论