1.并发&并行
并发:是指系统具有处理多个任务(动作)的能力---CPU切换速度快 但任务不在同一时间节点上跑
并行:是指系统具有同时处理多个任务(动作)的能力 --- 多核时 任务在同一时间节点上跑
并行是并发的子集
2.同步&异步
同步:当程序执行到一个IO(等待外部数据)的时候,你------等:同步 打电话
异步:当程序执行到一个IO(等待外部数据)的时候,你------不等:一直等到数据接收成功,再回来处理 发短信
3.GIL(Global Interprete Lock)全局解释器锁
''' 定义: 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.) ''' 结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
首先需要明确的一点是GIL
并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL
归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL
任务分两种:
1.IO密集型 (accept,recv) CPU会有空闲的时候 time.sleep()也等同于IO操作
2.计算密集型
对于IO密集型的任务,python的多线程是有意义的
可以采用多进程+协程利用多核
对于IO密集型的任务,python的多线程不推荐,python就不适用了
4.同步锁(也叫互斥锁)
三个需要注意的点:
#1.线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock仍然没有被释放则阻塞,即便是拿到执行权限GIL也要立刻交出来
#2.join是等待所有,即整体串行,而锁只是锁住修改共享数据的部分,即部分串行,要想保证数据安全的根本原理在于让并发变成串行,join与互斥锁都可以实现,毫无疑问,互斥锁的部分串行效率要更高
#3. 一定要看本小节最后的GIL与互斥锁的经典分析
import threading,time sum = 100 def sub(): global sum temp = sum time.sleep(0.1) #此时会发生时间轮循,有些线程来不及进行下一步就被解释器要求释放GIL锁 sum = temp - 1 l = [] for i in range(100): t = threading.Thread(target=sub) t.start() l.append(t) for a in l: a.join() print(sum)
此时输出结果是99
那么问题来了,怎么让sub函数在执行过程中不被CPU切换呢?------答案 同步锁
用锁把需要一次性由CPU执行的部分用acquire和release包起来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#同步锁 import threading,time sum = 100 def sub(): global sum lock.acquire() #同步锁 temp = sum time.sleep(0.1) #此时会发生时间轮循 sum = temp - 1 lock.release() l = [] lock = threading.Lock() for i in range(100): t = threading.Thread(target=sub) t.start() l.append(t) for a in l: a.join() print(sum)
因此以后在多个线程共享一个数据时,一定要酌情添加同步锁
5.死锁现象与递归锁
进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,Lock import time mutexA=Lock() mutexB=Lock() class MyThread(Thread): def run(self): self.func1() self.func2() def func1(self): mutexA.acquire() print('