昨日回顾
1 GIL锁:全局解释器锁,因为垃圾回收线程不是线程安全的,所有线程必须拿到这把锁,才能执行
2 GIL跟互斥锁的区别?GIL锁不能保证我们自己的数据安全,自己使用互斥锁保证自己的数据安全
3 不同线程数据交互两种方式:
-共享变量:不同线程修改同一份数据要加锁(互斥锁)
-通过queue:不需要考虑数据安全问题(线程安全了)
4 死锁现象:
-1 A线程拿到了A锁,等待B锁,B线程拿到了B锁,等待A锁,相互等待,永远等下去
-2 A线程拿到了A锁,再去拿A锁
5 递归锁(可重入锁):当前线程可以多次获得锁,每获得一次,计数器加一,每释放一次,计数器减一,只有计数器为0,其他线程才能获得
6 Event事件:(了解)
-event.set():发信号
-event.wait():阻塞等信号,只要收到set信号,就会继续往下执行
7 信号量:(了解),类似于锁,允许多条线程同时修改数据(有一些词,再不同环境下意思不一样)
8 Queue:三个:先进先出,后进先出,优先级 (线程Queue,跟进程的不是一个Queue)
9 池:池子,用来做缓冲
10 线程池:
from concurrent.futures import ThreadPoolExecutor
pool=ThreadPoolExecutor(5)
pool.submit(task,参数1,参数2).add_done_callback(回调函数)
11 进程池同理,用法完全一样,只是换一个类
from multiprocessing import Pool
p=Pool(3)
for url in urls:
p.apply_async(get_page,args=(url,),callback=pasrse_page)
12 并发:同一时间段内,多个任务执行(单核cpu可以实现),人跑步,鞋带开了,停下系鞋带,然后继续跑步,5分钟内,它干了两个是
并行:同一时刻,多个任务执行(单核cpu实现不了,必须多核),人跑步的同时听着歌
13 多核多线程比单核多线程更差,IO密集型用多线程,CPU(计算)密集型用多进程
今日内容
1 线程池和进程池的shutdown
from concurrent.futures import ThreadPoolExecutor
import time
pool = ThreadPoolExecutor(3)
def task(name):
print('%s 开始'%name)
time.sleep(1)
print('%s 结束'%name)
if __name__ == '__main__':
for i in range(20):
pool.submit(task, '屌丝%s' % i)
pool.shutdown(wait=True)
pool.submit(task,'sdddd')
print('主')
2 定时器
from threading import Timer
def task(name):
print('我是大帅比--%s'%name)
if __name__ == '__main__':
t = Timer(2, task,kwargs={'name':'lqz'})
t.start()
3 协程介绍
4 greenlet模块
from greenlet import greenlet
import time
def eat():
print('我吃了一口')
time.sleep(1)
print('我又吃了一口')
def play():
print('我玩了一会')
e.switch()
print('我又玩了一会')
if __name__ == '__main__':
e = greenlet(eat)
p = greenlet(play)
e.switch()
5 gevent模块
from gevent import monkey;monkey.patch_all()
import gevent
import time
def eat(name):
print('%s 吃了一口' % name)
time.sleep(1)
print('%s 又吃了一口' % name)
def play(name):
print('%s 玩了一会' % name)
time.sleep(2)
print('%s 又玩了一会' % name)
if __name__ == '__main__':
ctim = time.time()
e = gevent.spawn(eat,'lqz')
p = gevent.spawn(play,'lqz')
e.join()
p.join()
print('主')
print(time.time() - ctim)
6 单线程的套接字并发
7 asyncio
import time
import asyncio
from threading import current_thread
async def task():
print('开始了')
print(current_thread().name)
await asyncio.sleep(3)
print('结束了')
async def task2():
print('开始了')
print(current_thread().name)
await asyncio.sleep(2)
print('结束了')
loop=asyncio.get_event_loop()
ctime=time.time()
t=[task(),task2()]
loop.run_until_complete(asyncio.wait(t))
loop.close()
print(time.time()-ctime)
7 io模型(重点,抽象,难,面试重点)
1 内存分为内核缓冲区和用户缓冲区(网络下载的资源,硬盘加载的资源,先放到内核缓冲区----》copy到应用程序的缓冲区,应用程序才能用这个数据)
2 io模型:
-阻塞io(BIO)
-非阻塞io(NIO)
-io多路复用() select(windows支持,windows不支持epoll,官方不提供redis的window版本),poll,epoll(linux支持)
-异步io:
-信号驱动io(理论,不在考虑范围内)
补充虚拟环境
1 解决不同项目依赖的模块版本不同的问题
2 pycharm中创建项目时选择
-这个虚拟环境可不可以给其他项目使用(取决你是否选择)
-基于系统解释器当前状态还是纯净状态来创建虚拟环境
3 装模块:
-cmd窗口下:pip3 install flask (装在谁下,你一定要确认好)
-推荐你们用pycharm:setting---》那一套
-pycharm下的terminal下装(相当于cmd),比cmd好在,它有个提示
4 现在用了虚拟环境如何换到系统环境
4 环境变量的作用
-把一个路径加入到环境变量,以后该路径下的命令,可以再任意位置执行