生活中,你可以一边听歌,一边写作业,一边上网,一边吃饭……这些都是生活中多任务场景。电脑也可以执行多任务。比如你可以同时打开浏览器上网,听音乐啊等等。
并发和并行
并发:当有多个线程在操作时,如果系统只有一个CPU,则他根本不可能真正的同时进行一个以上的线程,它只能吧CPU运行时间划分为若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其他线程处于挂起状,这种方式我们称之为并发。
并行:当系统有一个以上CPU时,则线程的的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们能称之为并行。
– 多进程模式
– 多线程模式
– 协程
– 进程>线程>协程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及组织形式的描述,进程是程序的实体。
对于操作系统来说,一个任务就是一个进程。比方说打开浏览器就是启动一个浏览器的进程,在打开一个记事本就是启动一个记事本的进程,如果打开两个记事本就是启动两个记事本的进程。
优点:
- 稳定性高,一个进程崩溃了,不会影响其他进程。
缺点:
- 城建进程开销大;
- 操作系统能同时运行进程数目有限。
Linux和Unix操作系统提供了一个fork()函数创建新的进程,这也就意味着该函数仅适用于Linux和Unix平台。
fork()函数比较特殊,python的os.fork()是唯一调用返回两次的函数,因操作系统将当前的进程(父进程)复制了一份新的进程(子进程),然后分别在父进程和子进程内返回。
例如:采用父进程拷贝文件,子进程的拷贝并不是从开始就行的(除非进行设置),混乱拷贝文件可能出现结果异常而出现错误。
注意:有时在一个终端会混合出现打印结果。
fork()从本质上属于内建函数,通过os模块导入。
下面linux代码
import os
pid = os.fork()
if pid<0:
print("creat process failed")
elif pid == 0:
print("this is child process")
else:
print("this is parent process")
print("*******this end*******")
python代码
程序1
#进程创建
from multiprocessing import Process
from time import sleep
def task1():
while True:
sleep(1)
print('这是任务一...........')
def task2():
while True:
sleep(1)
print('这是任务二...........')
if __name__ == '__main__':
p1 = Process(target=task1,name='任务1')
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2')
p2.start()
print(p2.name)
结果1
任务1
任务2
这是任务一...........
这是任务二...........
这是任务一...........
这是任务二...........
这是任务一...........
这是任务二...........
这是任务一...........
结果分析;一直在运行
程序2
#进程创建
from multiprocessing import Process
from time import sleep
def task1():
while True:
sleep(1)
print('这是任务一...........')
def task2():
while True:
sleep(1)
print('这是任务二...........')
if __name__ == '__main__':
#子进程
p1 = Process(target=task1,name='任务1')
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2')
p2.start()
print(p2.name)
print('---------')
print('************************')
结果2
任务1
任务2
---------
************************
这是任务一...........
这是任务二...........
这是任务一...........
这是任务二...........
这是任务一...........
这是任务二...........
这是任务一...........
结果分析:(任务1任务2---------************************ )主进程运行完了,在进行子进程运行 (这是任务一…这是任务二…这是任务一…)
程序2
#进程创建
import os
from multiprocessing import Process
from time import sleep
def task1():
while True:
sleep(1)
print('这是任务一...........',os.getpid(),'-------',os.getppid())
def task2():
while True:
sleep(1)
print('这是任务二...........',os.getpid(),'-------',os.getppid())
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1')
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2')
p2.start()
print(p2.name)
print('---------')
print('************************')
结果2
8540
7864
任务1
任务2
---------
************************
这是任务一........... 7404 ------- 8540
这是任务二........... 10084 ------- 8540
这是任务一........... 7404 ------- 8540
这是任务二........... 10084 ------- 8540
结果分析:我们可以通过os.getpid()获得进程号
程序3
#进程创建
import os
from multiprocessing import Process
from time import sleep
def task1(s):
while True:
sleep(s)
print('这是任务一...........',os.getpid(),'-------',os.getppid())
def task2(s):
while True:
sleep(s)
print('这是任务二...........',os.getpid(),'-------',os.getppid())
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1',args=(1,))
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2',args=(2,))
p2.start()
print(p2.name)
print('---------')
print('************************')
结果3
14940
7864
任务1
任务2
---------
************************
这是任务一........... 9904 ------- 14940
这是任务二........... 14552 ------- 14940
这是任务一........... 9904 ------- 14940
这是任务一........... 9904 ------- 14940
这是任务二........... 14552 ------- 14940
这是任务一........... 9904 ------- 14940
这是任务一........... 9904 ------- 14940
这是任务二........... 14552 ------- 14940
这是任务一........... 9904 ------- 14940
结果分析:我们将task2(s),设置变量s,利用进程的属性 p2 = Process(target=task2,name=‘任务2’,args=(2,)),设置s时间秒数。()是元组,可迭代的,因此可以再放入两个或多个参数。
程序4
import os
from multiprocessing import Process
from time import sleep
def task1(s,name):
while True:
sleep(s)
print('这是任务一...........',os.getpid(),'-------',os.getppid(),name)
def task2(s,name):
while True:
sleep(s)
print('这是任务二...........',os.getpid(),'-------',os.getppid(),name)
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1',args=(1,'aa'))
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2',args=(2,'bb'))
p2.start()
print(p2.name)
print('---------')
print('************************')
结果4
14496
7864
任务1
任务2
---------
************************
这是任务一........... 11512 ------- 14496 aa
这是任务一........... 11512 ------- 14496 aa
这是任务二........... 1856 ------- 14496 bb
这是任务一........... 11512 ------- 14496 aa
这是任务二........... 1856 ------- 14496 bb
总结
from multiprocessing import Process
Process(target =函数,name=进程的名字,args = (给函数传递的参数))
process对象
对象调用方法:
process.start()启动进程并执行任务
process.run() 只是执行了任务,但是没有启动进程
terminate() 终止
举例:terminate()终止进程
程序5
import os
from multiprocessing import Process
from time import sleep
def task1(s,name):
while True:
sleep(s)
print('这是任务一...........',os.getpid(),'-------',os.getppid(),name)
def task2(s,name):
while True:
sleep(s)
print('这是任务二...........',os.getpid(),'-------',os.getppid(),name)
number = 1
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1',args=(1,'aa'))
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2',args=(2,'bb'))
p2.start()
print(p2.name)
while True:
number += 1
sleep(0.2)
if number == 20:
p1.terminate()
p2.terminate()
break
else:
print('---------number:',number)
print('---------')
print('************************')
结果5
13964
7864
任务1
任务2
---------number: 2
---------number: 3
---------number: 4
---------number: 5
---------number: 6
这是任务一........... 14508 ------- 13964 aa
---------number: 7
---------number: 8
---------number: 9
---------number: 10
---------number: 11
这是任务一........... 14508 -------这是任务二........... 13964 4488 aa-------
13964 bb
---------number: 12
---------number: 13
---------number: 14
---------number: 15
---------number: 16
这是任务一........... 14508 ------- 13964 aa
---------number: 17
---------number: 18
---------number: 19
---------
************************
Process finished with exit code 0
结果分析:当number == 20时,终止进程。
下面我么你分析全局变量的访问
程序6
import os
from multiprocessing import Process
from time import sleep
m = 1#全局变量
def task1(s,name):
global m #对全局变量进行修改,需要声明global
while True:
sleep(s)
m += 1
print('这是任务一...........',m)
def task2(s,name):
global m #对全局变量进行修改,需要声明global
while True:
sleep(s)
m += 1
print('这是任务二...........',m)
number = 1
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1',args=(1,'aa'))
p1.start() #start()是开进程做这个动作,run是直接做这个动作
print(p1.name)
p2 = Process(target=task2,name='任务2',args=(2,'bb'))
p2.start()
print(p2.name)
结果6
2288
7864
任务1
任务2
这是任务一........... 2
这是任务一........... 3
这是任务二........... 2
这是任务一........... 4
这是任务一........... 5
这是任务二........... 3
这是任务一........... 6
这是任务一........... 7
这是任务二........... 4
这是任务一........... 8
这是任务一........... 9
这是任务二........... 5
这是任务一........... 10
这是任务一........... 11
这是任务二........... 6
这是任务一........... 12
这是任务一........... 13
这是任务二........... 7
这是任务一........... 14
这是任务一........... 15
这是任务二........... 8
结果分析:m这个变量,放在全局变量里面,就相当于子进程自己也拥有了各自的m。
程序7
import os
from multiprocessing import Process
from time import sleep
m = 1#全局变量
def task1(s,name):
global m #对全局变量进行修改,需要声明global
while True:
sleep(s)
m += 1
print('这是任务一...........',m)
def task2(s,name):
global m #对全局变量进行修改,需要声明global
while True:
sleep(s)
m += 1
print('这是任务二...........',m)
number = 1
if __name__ == '__main__':
print(os.getpid())
print(os.getppid())
#子进程
p1 = Process(target=task1,name='任务1',args=(1,'aa'))
p1.start() #start()是开进程做这个动作,run是直接做这个动作
p2 = Process(target=task2,name='任务2',args=(2,'bb'))
p2.start()
while True:
sleep(1)
m += 1
print('------->main:',m)
结果7
15280
7864
------->main: 2
这是任务一........... 2
------->main: 3
这是任务一........... 3
这是任务二........... 2
------->main: 4
这是任务一........... 4
------->main: 5
这是任务一........... 5
这是任务二........... 3
------->main: 6
这是任务一........... 6
------->main: 7
这是任务一........... 7
这是任务二........... 4
------->main: 8
这是任务一........... 8
------->main: 9
这是任务一........... 9
这是任务二........... 5