进程:是CPU分配资源的最小单位
- CPU时间片:CPU处理的时间长度
- 进程是CPU分配资源的最小单位
- 光有进程没有办法高效里用CPU资源
- 处理进程等待时,进程会做IO等待,从而浪费时间,无法高效利用cpu
- 内存独立:
- 进程切换了,彼此多个进程不会影响
- A,B,C,3个进程相互独立,不管ABC怎么切换,数据不会乱
- 一个进程挂掉,其他进程不会有事情
线程:CPU执行的最小单位
- 轻量级的进程:线程是**内存共享**的
-
CPU寄存器,计算器
-
切换简单,CPU在切换执行任务的时候,损耗的时间少
- 但是由于线程存在GIL锁(Golbal Lock),维持全局的线程同步执行,导致最大的缺点就是没有办法实现真正并发
-
最大的优点是线程等待时IO可以切换,高效利用CPU资源
-
-
GIL锁的存在由此推论出Cpython中的多线程执行就是同步的:按照顺序,一个个来
-
进程:PID Process
-
线程也有:TID Thread
-
只在当前的内存空间下有用
-
-
线程如果父进程退出,那么全部子线程,都会退出
-
主线程死亡,子线程死亡
-
为了保持线程的稳定性,主线程一般不要做大事,不要业务处理,只做开启任务
- 没有孤儿线程,僵尸线程会有但是无所谓不重要
-
-
数据通信:
-
本身内存共享,list,dict,str,int,这些数据都可以直接共享
-
-
GIL:
-
大锁,全局锁,直接锁掉线程,维持全局的线程同步执行,影响并发,未来说不定这个东西就没有了
-
-
from threading import Thread
-
Process(target,args,)
-
t = Thread(target,args,name,kwargs)
-
t.start() 真正开启线程
-
t.join() 回收线程资源
-
-
-
#线程创建 from threading import Thread import time def work_a(a): for var in range(100000): a[0] += 1 def work_b(a): for var in range(100000): a[0] = a[0] * 3 def work_c(a): for var in range(50000): a[0] = a[0] - 1 def main(): a = [1] start = time.time() t = Thread(target=work_a,args=(a,)) t.start() t1 = Thread(target=work_b,args=(a,)) t1.start() t2 = Thread(target=work_c,args=(a,)) t2.start() for var in [t,t1,t2]: var.join() end = time.time() print('耗时:%.2f' % (end - start)) if __name__ == "__main__": main()
运行结果:
耗时:0.49
-
#线程数据共享,数据都可以直接共享 from threading import Thread def work_a(a): a[0] = 'a' def main(): a = [1] t = Thread(target=work_a,args=(a,)) t.start() t.join() print(a) if __name__ == "__main__": main()
运行结果:
['a']
-
列外:
- 只有纯计算没有IO的时候,多线程等同于单进程
- 甚至是多线程效率低于单进程
-
多进程:多核心电脑
-
计算密集的时候,多进程最快-->单进程-->多线程
-
-
多线程:
-
IO密集
- 比如:操作文件,QQ聊天的时候用多线程比较好
-
- 只有纯计算没有IO的时候,多线程等同于单进程
线程池:
from
multiprocessing.pool
import
ThreadPool
引入线程池模块
thread_pool
=
ThreadPool(
5
)
创建5个线程池
- p=thread_pool.apply_async(func,args,)
- 非阻塞行为,并发的,无序的
#非阻塞的会返回一个抽象的数据,调用值得时候需要用get函数(p.get())
- p.close(),p.join() 最后关闭跟回收线程