python基础day38 并发编程
进程概念
进程、线程都是操作系统中的基本概念,也就是说进程和线程都是操作系统层面的东西,专业术语表达就是进程和线程都是由操作系统来调度的,而不是由我们程序员自己来操控的。
在操作系统这门课里面,进程和线程是操作系统的概念,协程不是操作系统中的概念,而是我们程序员层面的
协程是由我们程序员自己来调用的,不是有操作系统来调用的,也就是说,在操作系统中没有协程这个概念
进程是用来做什么的:
可以用来做任务,比如:听歌、看视频等
什么是进程:
eg:厨师做饭,厨师按照菜谱来做菜,菜谱就是程序,而做饭的过程就是进程,在这个过程中,厨师就是线程,所以厨师才是真正做事的,言外之意线程才是真正干活的,而进程只是一个过程。
进程和程序的区别:
1. 程序就是一堆死的东西,没有生命周期
2. 进程是有生命周期的,当一个任务进行完毕之后,进程就不存在了
进程中是要有线程的,进程中如果没有线程是没有意义的,一个进程中至少要有一个线程,但可以有多个线程。
补充:CPU工作机制
1. 当CPU遇到 I/O 操作的时候,会剥夺CPU的执行权限
2. 当遇到的任务需要占用大量的时间的时候,也会剥夺执行权限
I/O密集型:
input output
遇到阻塞,但是不需要占用大量的CPU资源,需要等待,比如:sieep()
计算密集型
没有遇到阻塞,但是需要占用大量的CPU资源,也不需要等待
操作系统的调度算法(了解)
1. 先来先服务调度算法
2. 短作业优先调度算法
3. 时间片轮转法
4. 多级反馈队列
ps:操作系统会自行选择哪一种算法
进程的并发和并行
并行:在‘同一时刻’,同时执行任务
CPU是由多个核的:单核的、多核的
单核的CPU能不能做到并行? 做不到的
在同一时刻要想执行多个任务,必须要求CPU有多个处理器(核)
并发:在一段时间内,看起来是同时执行任务,事实上不是同一时刻
同步和异步、阻塞和非阻塞
同步:就是在发起一个调用时,在没有得到结果之前,该调用就不返回,但是一旦调用返回,就得到返回值了
异步:*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。
阻塞:是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞:指在不能立刻得到结果之前,该调用不会阻塞当前线程
可以产生四种调用方式:
同步阻塞式调用----------->效率最低
同步非阻塞式调用
异步阻塞式调用
异步非阻塞式调用-------->效率最高
如何开启进程
# 使用的是内置的模块:multiprocess from multiprocessing import Process def task(): with open('a.txt', 'w', encoding="utf8") as f: f.write('helloworld') # 开一个进程来执行task这个任务 # 如何开进程 """在Windows系统中,开启进程必须写在__main__中, 在其他系统中不用加""" if __name__ == '__main__': p = Process(target=task) # 得到一个对象,还没有开启进程呢,知识实例化了一个进程对象 p.start() # 调用这个方法才是真正的开启进程
Process类的参数
def task(name, name1, age, gender): print(name) print(name1) print("age:", age) print("gender:", gender) # import time # time.sleep(5) # with open('a.txt', 'w', encoding="utf8") as f: # f.write('helloworld') # task('kevin') # 开一个进程来执行task这个任务 # 如何开进程 """在Windows系统中,开启进程必须写在__main__中, 在其他系统中不用加""" if __name__ == '__main__': """ group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None 每一个进程都有:进程名,进程id等属性 name: 代表的是进程的名字 args=(), 传参数的 kwargs={}, daemon:守护进程 """ # p = Process(target=task) # 得到一个对象,还没有开启进程呢,知识实例化了一个进程对象 """这个开启进程只是通知操作系统去开进程,因为开启进程需要时间的,所以,在一瞬间进程并没有开起来,然后代码往下执行了""" # 开启的这个进程叫子进程 p = Process(target=task, name='ly_1', args=('kevin', 'jason'), kwargs={'age':18, 'gender':'male'}) # 得到一个对象,还没有开启进程呢,知识实例化了一个进程对象 # 守护进程的作用:主进程结束,子进程也结束 # 注意:p.daemon = True 必须要写在 p.daemon = True # 把p进程设置为守护进程p.start()之前 p.start() # 调用这个方法才是真正的开启进程 # 如何查看一个进程的名字 # Process-1, ly_1 # print(p.name) # 看的是p进程的名字 print("123") """现在的现象是:主进程代码先执行,然后执行子进程里的代码,并且主进程代码执行完毕之后,子进程的代码并没有结束"""
方法介绍
p.terminate() # 杀死进程 # True import time time.sleep(1) # False print(p.is_alive()) # 查看p进程是否存活 # join 现在让你先执行子进程中的代码,在执行主进程中的代码? p.join() # 先等待子进程执行完毕,在执行主进程
如何开启多进程
import time def task(i): print("task:", i) time.sleep(1) from multiprocessing import Process if __name__ == '__main__': start_time = time.time() ll = [] for i in range(5): # 开启多进程之后,有可能是没有顺序的 p = Process(target=task, args=(i, )) p.start() # p.join() # 5个进程变成了串行 ll.append(p) for j in ll: j.join() """想让所有的子进程先执行完,在执行主进程""" print(123) print("time:", time.time() - start_time)
进程锁
# 锁:以后你遇到的所有关于加锁的都是为了保证数据的安全 MySQL中:行锁、表锁、悲观锁、乐观锁、等 进程锁、互斥锁、GIL锁、死锁等 def task(i, lock): # 上一把锁 lock.acquire() print("第%s个进程进来了" % i) print("第%s个进程走了" % i) # 释放锁 lock.release() from multiprocessing import Process from multiprocessing import Lock if __name__ == '__main__': lock = Lock() for i in range(5): p = Process(target=task, args=(i, lock)) p.start()
进程间的通信(IPC机制)
进程是可以开启多个的,进程和进程之间是相互独立的,互不影响,进程是操作系统的一个独立单元,一个进程崩溃了,其他的进程不受影响,例如:在一个进程中不能修改另外一个进程中的数据
要想在一个进程中使用另外一个进程中的数据,需要让进程之间通信(IPC)