python并发编程之守护进程、互斥锁以及生产者和消费者模型
一、守护进程
主进程创建守护进程
守护进程其实就是'子进程'
一、守护进程内无法在开启子进程,否则会报错
二、进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束
守护进程简单实例:
from multiprocessing import Process import time def task(name): #此时的task为守护进程 print('%s is running' % name) #该行并不会被打印,因为主进程结束,守护进程会随之结束 time.sleep(3) if __name__ == '__main__': obj = Process(target=task, args=('egon',)) obj.daemon=True #一定要在obj.start()开启之前,将obj设置为守护进程,禁止obj创建子进程,否则就会报错 obj.start() # 发送信号给操作系统开启一个进程(守护进程) print('主') #并且主进程结束,守护进程也会随之结束
为什么要用守护进程:
两方面理解:
一、进程:为了让父进程的任务能够并发的执行,需要将该任务放到子进程中去
二、守护:是因为子进程中执行的任务,在父进程运行完就没有存在的意义了,就设置成守护进程,会在父进程结束后,守护进程也随之结束
由于计算机的性能的原因,进程打印出的结果可能会有不同的结果:
from multiprocessing import Process import time def foo(): #主进程结束,守护进程就会结束 print(123) time.sleep(1) print("end123") def bar(): #正常的子进程,父进程会等正常的子进程结束才会结束(父进程可以看到子进程的pid) print(456) time.sleep(3) print("end456") if __name__ == '__main__': p1=Process(target=foo) #把p1做成守护进程 p2=Process(target=bar) #正常的子进程 p1.daemon=True #一定要在开启子进程之前,否则会报错,守护进程会伴随主进程的代码的运行完毕而死掉 p1.start() p2.start() print("main-------") #主进程结束,守护进程也随之结束 #正常机器 ''' main------- 456 end456 ''' #快一点机器 ''' main------- #申请一个内存空间,然后调用操作系统,将其打印到终端 123 #机器性能好的话,可能在打印的时候,p1进程已经起来了,即向操作系统发送请求后,很快就做出回应开启了子进程 456 end456 ''' # 机器更快 ''' 123 #当机器的性能在好一点,有可能会出现,p1向操作系统发起开启子进程的请求,迅速做出回应,然后开启子进程,那么123就会优先main先被打印出来 main------- 456 end456 '''
二、互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一套文件,或同一个打印终端是没问题的
然而共享带来的是竞争,竞争带来的就是错乱无序,所以我们要加锁进行处理
多个进程共享同一个打印终端
'''能不自己处理锁,就尽量不用锁,''' #进程间通信,一个进程修改后,其他进程能看到修改后的结果 '''互斥所就是把并发变成串行,保证了数据安全,但是牺牲了效率''' '''锁同一时间锁只能被一个子进程抢,用完了再释放掉,才能被其他进程抢到再用''' """互斥锁可以将要执行代码的(部分共享的数据)变成串行,而join是将要执行代码所有部分变成串行""" # 互斥锁: #强调:必须是lock.acquire()一次,然后 lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire() # 互斥锁vs join的区别一: # 大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序 # 区别:join是按照人为指定的顺序执行,而互斥锁是所以进程平等地竞争,谁先抢到谁执行 # 没加锁之前,打印会变的错乱 # 并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import time,random def task1(): #为每一个进程加上一把锁,这样就会有和join一样的效果,变成了串行 print('task1:名字是egon') time.sleep(random.randint(1,3)) print('task1:性别是male') time.sleep(random.randint(1,3)) print('task1:年龄是18') def task2(): print('task2:名字是alex') time.sleep(random.randint(1,3)) print('task2:性别是male') time.sleep(random.randint(1,3)) print('task2:年龄是78') def task3(): print('task3:名字是lxx') time.sleep(random.randint(1,3)) print('task3:性别是female') time.sleep(random.randint(1,3)) print('task3:年龄是30') if __name__ == '__main__': p1=Process(target=task1) p2=Process(target=task2) p3=Process(target=task3) p1.start() p2.start() p3.start() ''' 运行结果: task1:名字是egon task3:名字是lxx task2:名字是alex task1:性别是male task3:性别是female task2:性别是male task1:年龄是18 task3:年龄是30 task2:年龄是78 '''